2012-04-04 12 views
1

Ich habe versucht, dieses Bit Code ohne Erfolg zu arbeiten. gdb sagt mir, dass es eine segfault irgendwo im leeren Raum Compiler :: GenerateCode_ToFile (char * filename) Funktion, und ich habe das Problem manuell zu irgendwo in der Linie verfolgt:Crash/Segfault beim Aufruf des virtuellen Members der Unterklasse

std::string tempfile = this->code->CodeGen(temp, AST_TYPE_UNDEF, symtab, 0); 

aber nicht, nachdem er oder sie vor . Außerdem scheint es zu stürzen, bevor irgendein Code dieser virtuellen Funktion ausgeführt wird.

Kann jemand das Problem hier sehen? Ich kann nicht sehen, was es zum Absturz bringt. Diese ist die Funktion, die virtuelle Funktion aufruft:

void Compiler::GenerateCode_ToFile(char* filename){ 

char directory[MAX_PATH]; //Actually represents the full path. 
strcpy(directory, this->cwd.c_str()); 
strcat(directory, filename); 

if(this->isVerboseMode) 
    std::cout << "Source Output: " << directory << '\n'; 

std::fstream file(directory, std::ios::out); 

int* temp = new int; 
Symtable* symtab = new Symtable; 
file << emit_core_code(); 
file << "\n\n"; 
std::string tempfile = this->code->CodeGen(temp, AST_TYPE_UNDEF, symtab, 0); 
file.close(); 
} 

Dies ist die Definition der Klasse von this- vertreten> Code.

/// CollectionExprAST - Expression class for multiple branches. 
class CollectionExprAST : public ExprAST { 
    std::vector<ExprAST*>* Code; 
public: 
    CollectionExprAST(std::vector<ExprAST*>* code) : Code(code) {} 
    virtual std::string CodeGen(int* GeneratedCodeOpType,int WantOpType,Symtable* symtab, int depth); 
    int GetType(void){return AST_TYPE_COLLECTION;}; 
    void* GetCollection(void){return this->Code;}; 
    void DebugPrint(int level); 
}; 

Dies ist seine Superklasse:

/// ExprAST - Base class for all expression nodes. 
class ExprAST { 
public: 
    virtual ~ExprAST() {} 
    virtual std::string CodeGen(int* GeneratedCodeOpType,int WantOpType,Symtable* symtab, int depth) {return std::string("");}; 
    virtual void DebugPrint(int level){return;}; 
    virtual int GetType(void){return AST_TYPE_UNDEF;}; 
    virtual void* GetCollection(void){return NULL;}; 
}; 

und schließlich ist dies die virtuelle Funktion, die aufgerufen wird (obwohl vor scheint zum Absturz bringen es ausgeführt wird):

std::string CollectionExprAST::CodeGen(int* GeneratedCodeOpType,int WantOpType,Symtable* symtab, int depth) 
{ 
Sleep(3000); 
std::string ret; 
int j=0; 
for(;j<this->Code->size();j++){ 
    int temp; 
    int i=0; 
    for(;i<depth;i++) 
     ret += "\t"; 
    ret += (*this->Code)[j]->CodeGen(&temp,WantOpType,symtab, depth+1); 
    ret += '\n'; 
} 
return ret; 
} 

I Ich weiß, dass es abstürzt, bevor es ausgeführt wird, da Sleep() nie ausgeführt wird.

Kann jemand den Fehler sehen, der diesen mysteriösen segfault verursacht?

Vielen Dank im Voraus.

+1

Zu viel Code. Sie müssen einen [minimalen Testfall] erstellen (http://sscce.org), bevor Sie Ihren Code hier veröffentlichen. Sind Sie sicher, dass z. 'this-> code' ist ein gültiger Zeiger? –

+0

@OliCharlesworth Ich bin relativ sicher, dass es ein gültiger Zeiger ist, da ich andere virtuelle Mitglieder ohne Probleme anrufe. –

+0

@ 64bit_twitchyliquid: Sie müssen einen minimalen Testfall konstruieren, bevor jemand hier Ihnen konkrete Hilfe geben kann. –

Antwort

1

Der Grund ist, dass code nicht zugeordnet oder beschädigt ist.

Suchen Sie nach nil, bevor Sie die Funktion ausführen, und überprüfen Sie, ob Sie eine andere Funktion von diesem Zeiger ausführen können. Der erste wird offensichtlich sein, letzterer kann bedeuten, dass der Zeiger irgendwo beschädigt wurde.

+0

Millisekunden zuvor wird eine andere virtuelle Funktion aufgerufen (DebugPrint()) und es wird korrekt ausgeführt. Bist du sicher, dass Code das Problem ist? –

+0

greift DebugPrint() auf alle Felder des Objekts zu? Ist dies nicht der Fall, wird das Objekt überhaupt nicht ausgeführt. –

+0

Ja. Es verwendet ziemlich alle von ihnen. –

1

Ich sehe nirgendwo in Ihrem Beispiel, wo Sie tatsächlich die Code Mitgliedsvariable zuweisen. Es ist ein Zeiger und worauf es hinweist, muss irgendwann zugewiesen werden.

Es gibt auch andere Probleme, die jedoch nicht direkt mit Ihrem Absturz zusammenhängen.

Zuerst löschen Sie niemals symtab oder temp in GenerateCode_ToFile. Dies ist ein Speicherleck. Warum in der Welt sind Sie dynamisch ein int da? Erklären Sie einfach einen int auf dem Stack und übergeben Sie seine Adresse an die CodeGen Funktion. Das Gleiche gilt für symtab wenn möglich.

int i = 10; 
SomeFuncThatTakesAPointer(&i); 

Eigentlich genaueres Hinsehen, Sie verwenden nicht einmal die int* Parameter in der Funktion und es ist nicht überall gespeichert, so dass nur vollständig, es loszuwerden.

Weiter ...

std::vector<ExprAST*>* Code; 

Zeiger auf Vektoren und Vektoren, die Zeiger zu speichern sind fast immer falsch. Sie verhindern, dass der Vektor die dynamische Speicherzuweisung und Freigabe für Sie verarbeitet.Sie können auch ein Array an dieser Stelle verwenden (ok, ein Array wächst nicht für Sie, wenn Sie etwas über seine Grenzen hinaus zuweisen, aber immer noch, schlechte Praxis).

Vektoren verwenden ein Muster namens RAII, um die sichere Zuordnung und Freigabe von Speicher für Sie zu verwalten. Wenn Sie einen Zeiger auf einen Vektor pflegen, umgehen Sie diesen Prozess und müssen delete auf dem Vektor selbst aufrufen.

Wenn Sie Zeiger in einem Vektor speichern, verhindern Sie erneut, dass der Vektor seine gespeicherten Objekte freigibt. Es speichert die Zeiger selbst dynamisch und ruft delete auf ihnen auf, aber das wird nicht aufheben, worauf der ursprüngliche Zeiger hinwies.

C++ ist eine komplexe Sprache. Ich schlage vor, einige Zeit damit zu verbringen, mehr über Speicherverwaltung im Allgemeinen und Muster wie RAII zu lernen, die den Prozess für Sie vereinfachen können.

Verwandte Themen