2012-04-10 19 views
0

Ich habe eine C++ Klasse Matrix22 mit einem Array und einem Standard-Konstruktor:Warum reserviert der Compiler nicht genügend Speicherplatz auf dem Stack?

class Matrix22{ 
    /* something more */ 
    double mat[2][2]; 
    Matrix22(){ 
    for(int i=0; i<2; i++) 
     for(int j=0; j<2; j++) 
     mat[i][j] = i==j ? 1.0 : 0.0; 
    } 
}; 

Ich habe es in meinem Programm und einen Segmentation Fault bekam. Da der Rest ziemlich schwierig und kompliziert war, schrieb ich eine einfache Testroutine, die einfach Matrix22() aufruft. Kein Seg-Fehler mehr.

Ich lief dann gdb, um das Problem zu debuggen. Wenn ich den Konstruktor aus der separaten Testroutine aufrufe, reserviert gcc Speicherplatz für das Element mat. Ich kann durch den Stapel navigieren und die Rücksprungadresse einige Bytes nach dem Array sehen.

Im Hauptprogramm reserviert der Compiler nicht genügend Speicherplatz. Das erste Element (mat[0][0]) wird geschrieben, aber jedes weitere Schreiben überschreibt einfach den nächsten Stapelrahmen. Ich kann auch überprüfen, dass wie vor dem Konstruktor der Befehl bt ein korrektes Backtrace zurückgibt, wobei nach der kritischen Zuweisung das Backtrace beschädigt ist.

Also meine Frage ist: Warum reserviert in einem Fall der Compiler (oder der Linker?) Nicht genug Platz für das Array, während im anderen Fall das nicht passiert?

PS: Beide "Testfälle" sind mit dem gleichen Compiler und Flags kompiliert und auch gegen die gleichen Objektdateien gekoppelt.

edit:

Hier ist der "einfache" Testfall, der ohne seg Fehler funktioniert:

void test_Matrix22() 
{ 
    Framework::Math::Matrix22 matrix; 
} 

Der Code mit einem seg Fehler erzeugt in der Klasse ModuleShaddower (vermischte Header und Implementierung):

class ModuleShaddower{ 
    public: 
     ModuleShaddower(PVModule& module, const EnvironmentalSetup& setup, const Position& position); 
    private: 
     Matrix22 rotMatrix90; 
}; 

ModuleShaddower::ModuleShaddower(PVModule& module, const EnvironmentalSetup& setup, const Position& position) 
    : module (module), position(position), setup(setup), logger(LoggerFactory::getLoggerInstance()) 
{ 
    double mat[][2] = {{0, -1},{1, 0}}; // This line will never be reached 
    rotMatrix90 = Matrix22(mat); 
} 

Wie Sie sehen, es ist ganz aus dem Rest. Ich werde vielleicht versuchen, den problematischen Code zu extrahieren, aber ich denke, das wird nicht viel helfen.

+0

Können Sie den vollständigen Testfall bereitstellen? (die eine, die fehlschlägt) –

+0

Was Oli sagte: Zeigen Sie uns, wie Sie die Klasse verwenden. –

+0

Der kurze Test ist kein Problem. Die lange Version hat mehrere tausend Zeilen Code. Ich werde versuchen, einen Teil davon zu geben –

Antwort

0

Das Problem lag an der Tatsache, dass zwei Objektdateien an verschiedenen Orten denselben Namen hatten. In der resultierenden statischen Bibliothek, die aus diesem Objektcode erstellt wurde, wird manchmal die falsche Datei ersetzt (beide wurden Shaddower.o genannt). Als ich eine der Dateien umbenannte, ging alles gut und keine Fehler mehr.

Ich kenne den genauen Ursprung dieses Problems nicht, aber es ist so lösbar.

0

Wenn Ihr ModuleShaddower-Contructor-Code nicht erreicht wird (gemäß Ihrem Code-Kommentar), verursacht etwas in Ihrer Konstruktor-Initialisierungsliste (im Zusammenhang mit der Konstruktion des Moduls, der Positionierung usw.) das Problem.

+0

Ich würde dir zustimmen. Aber wenn ich mit dem Debugger durchgehe, gebe ich den Konstruktor Matrix22() ein. Zu Beginn ist der Stack in Ordnung (über 'bt' geprüft). Nachdem die Schleifen durchlaufen wurden, ist der Stapel beschädigt. Für mich ist es klar, dass der problematische Code innerhalb des Matrix22() Konstruktors liegt. PS: Die anderen Parameter sind alle Referenzen. Sie werden draußen ohne Probleme erstellt. Wenn sie das Problem wären, sollte das ganze Problem meiner Meinung nach an einer anderen Stelle passieren oder liege ich falsch? –

Verwandte Themen