Paar Fehler (hat vielleicht was mit static zu tun)
-
Hallo,
bin grade etwas am verzweifeln. Und zwar bekomm ich folge Fehler:
stefan@stefan-laptop:~/Downloads/Version 1 P1 fertig$ make
g++ test.o rmmixalTables.o SymbolTable.o RMMIXinstruction.o RMMIXparser.o rmmixHardware.o rmminixos.o Festplatte.o MMU.o Page.o -o test
rmmixHardware.o: In functionFestplatte::load(std::basic\_string<char, std::char\_traits<char>, std::allocator<char> >, int)': rmmixHardware.cpp:(.text.\_ZN10Festplatte4loadESsi[Festplatte::load(std::basic\_string<char, std::char_traits<char>, std::allocator<char> >, int)]+0x2e): undefined reference toFestplatte::Seiten'
rmmixHardware.cpp:(.text._ZN10Festplatte4loadESsi[Festplatte::load(std::basic_string<char, std::char_traits<char>, std::allocator<char> >, int)]+0x6e): undefined reference toFestplatte::Seiten' rmmixHardware.cpp:(.text.\_ZN10Festplatte4loadESsi[Festplatte::load(std::basic\_string<char, std::char_traits<char>, std::allocator<char> >, int)]+0xd7): undefined reference toFestplatte::Seiten'
rmmixHardware.o: In functionMMU::isTabelleVorhanden(std::basic\_string<char, std::char\_traits<char>, std::allocator<char> >)': rmmixHardware.cpp:(.text.\_ZN3MMU18isTabelleVorhandenESs[MMU::isTabelleVorhanden(std::basic\_string<char, std::char_traits<char>, std::allocator<char> >)]+0x2c): undefined reference toMMU::Tabellenliste'
rmmixHardware.o: In functionMMU::einlagern(std::basic\_string<char, std::char\_traits<char>, std::allocator<char> >, int)': rmmixHardware.cpp:(.text.\_ZN3MMU9einlagernESsi[MMU::einlagern(std::basic\_string<char, std::char_traits<char>, std::allocator<char> >, int)]+0x89): undefined reference toMMU::Tabellenliste'
rmmixHardware.cpp:(.text._ZN3MMU9einlagernESsi[MMU::einlagern(std::basic_string<char, std::char_traits<char>, std::allocator<char> >, int)]+0xb5): undefined reference toMMU::Tabellenliste' rmmixHardware.cpp:(.text.\_ZN3MMU9einlagernESsi[MMU::einlagern(std::basic\_string<char, std::char_traits<char>, std::allocator<char> >, int)]+0x109): undefined reference toMMU::Counter'
rmmixHardware.cpp:(.text._ZN3MMU9einlagernESsi[MMU::einlagern(std::basic_string<char, std::char_traits<char>, std::allocator<char> >, int)]+0x112): undefined reference toMMU::Counter' rmmixHardware.o: In functionMMU::translate(std::basic_string<char, std::char_traits<char>, std::allocator<char> >, int)':
rmmixHardware.cpp:(.text._ZN3MMU9translateESsi[MMU::translate(std::basic_string<char, std::char_traits<char>, std::allocator<char> >, int)]+0x60): undefined reference toMMU::Tabellenliste' rmmixHardware.cpp:(.text.\_ZN3MMU9translateESsi[MMU::translate(std::basic\_string<char, std::char_traits<char>, std::allocator<char> >, int)]+0xa7): undefined reference toMMU::Tabellenliste'
rmmixHardware.cpp:(.text._ZN3MMU9translateESsi[MMU::translate(std::basic_string<char, std::char_traits<char>, std::allocator<char> >, int)]+0xd0): undefined reference toMMU::Tabellenliste' Festplatte.o: In functionFestplatte::Festplatte()':
Festplatte.cpp:(.text+0x18): undefined reference toFestplatte::Seiten' Festplatte.o: In functionFestplatte::Festplatte()':
Festplatte.cpp:(.text+0x3c): undefined reference toFestplatte::Seiten' MMU.o: In functionMMU::MMU()':
MMU.cpp:(.text+0x15): undefined reference toMMU::Counter' MMU.cpp:(.text+0x1f): undefined reference toMMU::Zeiger'
MMU.o: In functionMMU::MMU()': MMU.cpp:(.text+0x3f): undefined reference toMMU::Counter'
MMU.cpp:(.text+0x49): undefined reference to `MMU::Zeiger'
collect2: ld returned 1 exit status
make: *** [test] Fehler 1Die MMU.h (in der cpp hab ich kaum was drin)
#ifndef MMU_H #define MMU_H #include <string> #include "Festplatte.h" using namespace std; #define INDEX 1 #define TRANSLATED 2 class MMU { public: static const int maxProzesse = 20; // Anzahl von Seitentabellen (eine je Prozess) static const int maxPage = 8; // Virtueller Adressraum in 512 Worten static const int HardwareSize = 4; // Physikalischer Adressraum in 512 Worten static const int PageSize = 512; struct Tabelle { string Prozess; int Seitentabelle [maxPage][2]; }; public: static Tabelle Tabellenliste[maxProzesse]; static int Zeiger; static int Counter; static bool isTabelleVorhanden(string job) { for (int i = 0; i < maxProzesse; i++) { if (Tabellenliste[i].Prozess == job) return true; } return false; } static void einlagern(string job, int Seite) { if (!MMU::isTabelleVorhanden(job)) { for (int i = 0; i < maxProzesse; i++) { if (Tabellenliste[i].Prozess == "") { Tabellenliste[i].Prozess = job; } } } if (Counter >= HardwareSize) { // es gibt kein Platz, andere Seite entfernen } // neue Seite einfügen Festplatte::load(job, Seite); Counter++; } public: MMU(); MMU(const MMU& orig); virtual ~MMU(); static int translate(string job, int virtuelle) { int Seite = virtuelle / PageSize; int Offset = virtuelle % PageSize; for (int i = 0; i < maxProzesse; i++) { if (MMU::Tabellenliste[i].Prozess == job) { // finde Seitentabelle zum Prozess for (int t = 0; t < maxPage; t++) { if (MMU::Tabellenliste[i].Seitentabelle[t][INDEX] == Seite) { // Seite eingelagert? return (MMU::Tabellenliste[i].Seitentabelle[t][TRANSLATED] * PageSize + Offset); } } // Seite muss eingelagert werden MMU::einlagern(job, Seite); return translate(job, virtuelle); } } // Seite muss eingelagert werden MMU::einlagern(job, Seite); return translate(job, virtuelle); } }; #endif /* MMU_H */und teil rmmixHardware.cpp:
case RMMIXAL::LDWI: cout << instruction.fields[2] << "#1"; registers[ instruction.fields[1] ] = dataMemory[MMU::translate(instruction.JobName, instruction.fields[2])]; break; case RMMIXAL::LDW: cout << registers[ instruction.fields[2] ] << "#2"; registers[ instruction.fields[1] ] = dataMemory[ registers[MMU::translate(instruction.JobName, instruction.fields[2])] ]; break; case RMMIXAL::STWI: cout << instruction.fields[2] << "#3"; dataMemory[MMU::translate(instruction.JobName, instruction.fields[2])] = registers[ instruction.fields[1] ]; break; case RMMIXAL::STW: cout << instruction.fields[2] << "#4"; dataMemory[ registers[MMU::translate(instruction.JobName, instruction.fields[2]) ] ] = registers[ instruction.fields[1] ]; break;naja verwende zum ersten mal static in c++. Da ich eh nur eine Festplatte und MMU habe brauch ich so nicht die ganze Zeit die Variablen mitübergeben.
Hab das komplette Projekt mal hochgeladen:
http://www.file-upload.net/download-3088858/Version-1-P1-fertig.tar.gz.html
(läuft evtl. nur unter Linux)Gruß
Geddon
-
Hast Du daran gedacht, daß Du für statische Membervariablen Speicherplatz (außerhalb der Klassendefinition) zur Verfügung stellen mußt?
class Beispiel { static int i; } int Beispiel::i;
-
Belli hat recht.
class foo { static int bar; // <-- DeKLARAtion }; int foo::bar; // <-- DeFINItionBei Dir fehlen die Definitionen der statischen Datenelemente.
Dass Du überhaupt eine Klasse mit statischen Datenelementen als Abstraktion wählst, finde ich seltsam. Warum nicht einfach nur freie Funktionen?
Header:
#ifndef FESTPLATTE_HPP_INCLUDED #define FESTPLATTE_HPP_INCLUDED int dies(); void das(int); #endif // FESTPLATTE_HPP_INCLUDEDcpp-Datei:
#include "festplatte.hpp" namespace { int fp_zustand = 0; } // anonymer Namensraum int dies() { return fp_zustand; } void das(int x) { fp_zustand = x; }Beachte: Es tauchen keine Deklarationen von Objekten mit statischer Lebensdauer im Header auf.
edit: copy&paste fehler entfernt
-
krümelkacker schrieb:
Dass Du überhaupt eine Klasse mit statischen Datenelementen als Abstraktion wählst, finde ich seltsam. Warum nicht einfach nur freie Funktionen?
Lass mich raten... du nutzt auch keine namespaces?
-
wxSkip schrieb:
Lass mich raten... du nutzt auch keine namespaces?
Ich nutze sowohl sowohl Klassen als auch Namensräume. Beispielsweise habe ich in dem obigen Beispiel einen anonymen Namensraum verwendet. Ich sehe nur keinen Sinn darin, in diesem Fall eine Klasse mit ausschließlich statischen Elementen zu definieren. Es bringt doch nichts. Im Gegenteil: Man muss so im Header auch verraten, was für Variablen für die Verwaltung des Zustands benötigt werden.
btw: Ich find's schade, dass Dein kompletter "Beitrag" sich auf diese eine Zeile beschränkt hat, die ich zitiert habe. Hättest ja auch mal erläutern können, warum eine Klasse hier angeblich sinvoll eingesetzt werden könne.
Eben beim Überfliegen des Originalposts habe ich noch ein "using namespace std;" in einer Header-Datei entdeckt. Das gehört sich natürlich nicht und muss auch mal erwähnt werden.
-
Okay, der war ein bisschen knapp. Warum verwendest du anonyme Namespaces? Den Sinn kenne ich nicht.
Der Sinn davon, eine Klasse mit statischen Membern statt eines namespace zu verwenden, ist IMHO, dass du globale Variablen private machen kannst. Der Nachteil ist natürlich, dass du keine using-Deklarationen verwenden kannst.
Wobei sich das mit den Variablen natürlich relativiert, wenn du sie in der Implementationsdatei deklarierst (du hättest bloß noch Probleme bei Mehrfachdeklaration in einer anderen C++-Datei).
-
wxSkip schrieb:
Warum verwendest du anonyme Namespaces? Den Sinn kenne ich nicht.
Damit man die enthaltenen Objekte von einer anderen Übersetzungseinheit aus nicht direkt ändern kann und um Namenskollisionen aus dem Weg zu gehen, habe ich sie eingesetzt. Quasi "private" auf Ebene der Übersetzungseinheiten. Sonst könntest Du in einer anderen ÜE einfach schreiben
extern int fp_zustand;und darüber den Wert von fp_zustand manipulieren. Alternativ kannst Du natürlich fp_zustand mit interner Bindung deklarieren. Das wäre aber nicht im Sinne des C++-Erfinders.