bds 2006 C versteckte Speichermanager Konflikte (class neu / löschen vs AnsiString)

Ich benutze BDS 2006 Turbo C ++ schon lange und einige meiner größeren Projekte ( CAD / CAM, 3D- Grafikprozessoren und Astronomische Berechnungen) casting gelegentlich eine Ausnahme auf (zum Beispiel einmal in 3-12 Monaten von 24/7 Heavy-Duty-Nutzung) ). Nach umfangreichem Debugging habe ich folgendes gefunden:

//code1: struct _s { int i; } // any struct _s *s=new _s[1024]; // dynamic allocation delete[] s; // free up memory 

Dieser Code ist normalerweise innerhalb einer Vorlage, wo _s auch eine class sein kann daher delete[] Dieser Code sollte korrekt funktionieren, aber delete[] funktioniert nicht richtig für Strukturen (classn sieht OK aus). Es werden keine Ausnahmen ausgetriggers, der Speicher wird freigegeben, aber die Speichermanager-Zuordnungstabellen werden beschädigt, und danach kann jede neue Zuweisung falsch sein (neue können überlappende Zuweisungen mit bereits zugewiesenem Speicherplatz oder sogar nicht zugewiesenem Speicherplatz erstellen, daher die gelegentlichen Ausnahmen)

Ich habe festgestellt, dass, wenn ich einen leeren Destruktor zu _s hinzufüge, plötzlich alles in Ordnung scheint

 struct _s { int i; ~_s(){}; } 

Nun, jetzt kommt der komische Teil. Nachdem ich dies auf meine Projekte aktualisiert habe, habe ich festgestellt, dass die AnsiString class auch schlechte Reallokationen hat. Beispielsweise:

 //code2: int i; _s *dat=new _s[1024]; AnsiString txt=""; // setting of dat for (i=0;i<1024;i++) txt+="bla bla bla\r\n"; // usage of dat delete[] dat; 

In diesem Code enthält dat einige nützliche Daten, später gibt es einige txt Strings, die durch Hinzufügen von Zeilen erstellt wurden, so dass der txt mehrmals neu txt muss und manchmal die txt mit txt überschrieben werden (auch wenn sie nicht überlappt sind, AnsiString ich an den AnsiString neu zu txt ist mit dat überlappt)

Also meine Fragen sind:

  1. Mache ich etwas falsch in Code1, Code2?
  2. Gibt es eine Möglichkeit, AnsiString (Neu-) Zuordnungserrors zu vermeiden? (aber immer noch damit)

    • Nach ausführlichem Debugging (nachdem ich Frage 2 gestellt habe) habe ich festgestellt, dass AnsiString keine Probleme verursacht. Sie treten nur während ihrer Verwendung auf. Das eigentliche Problem besteht wahrscheinlich darin, zwischen OpenGL- Clients zu wechseln. Ich habe Öffnen / Speichern-Dialoge mit Vorschau für Vektorgrafiken. Wenn ich die OpenGL- Verwendung für diese VCL- Unterfenster als AnsiString deaktiviere, AnsiString Speicherverwaltungserrors vollständig. Ich bin nicht Shore, was ist das Problem (Inkompatibilität zwischen MFC / VCL- Windows oder wahrscheinlicher habe ich einen Fehler bei der Umstellung von Kontexten gemacht, wird weiter untersuchen). Betroffene OpenGL- Fenster sind:
    • Haupt- VCL- Formular + OpenGL innerhalb des Canvas Clientbereichs
    • untergeordnetes MFC Öffnen / Speichern-Dialogfeld + angedockte Vorschau VCL- Formular + OpenGL innerhalb des Canvas Clientbereichs

PS

  1. Diese Fehler hängen von der Anzahl der new/delete/delete[] Verwendungen ab, nicht von den zugewiesenen Größen
  2. Sowohl der code1 als auch der code2 Fehler wiederholen sich (zum Beispiel muss ein Parser komplexe ini Dateien laden und der Fehler tritt in derselben Zeile auf, wenn das ini nicht geändert wird)
  3. Ich erkenne diese Fehler nur bei großen Projekten (einfacher Quelltext> 1MB) mit kombinierter Verwendung von AnsiString und Templates mit internen dynamischen Zuordnungen, aber es ist möglich, dass sie auch in einfacheren Projekten vorkommen, aber so selten vorkommen, dass ich sie vermisse.
  4. Infizierte Projektspezifikationen:
    • win32 noinstall standalone (mit Win7sp1 x64 aber auf XPsp3 x32 verhält sich das gleiche)
    • misst nicht, wenn GDI oder OpenGl / GLSL verwendet wird
    • Zähler nicht, wenn Gerätetreiber- DLLs verwendet werden oder nicht
    • keine OCX oder nicht standardmäßige VCL- Komponente
    • kein DirectX
    • 1 Byte ausgerichtete Kompilierung / Link
    • Verwenden Sie keine RTL , Pakete oder Frameworks (Standalone)

Sorry für schlecht Englisch / Grammatik … jede Hilfe / Schlussfolgerung / Vorschlag geschätzt.

   

Nach eingehender Fehlersuche habe ich das Problem fein isoliert. Die Speicherverwaltung von bds2006 Turbo C ++ wurde beschädigt, nachdem Sie versucht haben, eine Löschung für bereits gelöschte pointers aufzurufen. beispielsweise:

 BYTE *dat=new BYTE[10],*tmp=dat; delete[] dat; delete[] tmp; 

Danach ist die Speicherverwaltung nicht zuverlässig. (‘neu’ kann bereits zugewiesenen Speicherplatz zuweisen)

Natürlich ist das Löschen des gleichen pointerss zweimal ein Fehler auf der Programmiererseite, aber ich habe die wahre Ursache aller meiner Probleme gefunden, die dieses Problem erzeugen (ohne offensichtlichen Fehler im Quellcode).

 //--------------------------------------------------------------------------- class test { public: int siz; BYTE *dat; test() { siz=10; dat=new BYTE[siz]; } ~test() { delete[] dat; // < - add breakpoint here siz=0; dat=NULL; } test& operator = (const test& x) { int i; for (i=0;i 

In der function get() heißt Destruktor für die class a zweimal. Einmal für echt und einmal für seine Kopie, weil ich vergessen habe, Konstruktor zu erstellen

 test::test(test &x); 

[Edit1] weitere Upgrades des Codes

OK Ich habe den Initialisierungscode für classn- und Struct-Templates verfeinert, um noch mehr Bug-Fälle zu beheben. Fügen Sie diesen Code jeder Struktur / class / Vorlage hinzu und fügen Sie bei Bedarf functionen hinzu

 T() {} T(T& a) { *this=a; } ~T() {} T* operator = (const T *a) { *this=*a; return this; } //T* operator = (const T &a) { ...copy... return this; } 
  • T ist der Name der Struktur / class
  • Der letzte Operator wird nur benötigt, wenn T dynamische Zuordnungen verwendet. Wenn keine Zuweisungen verwendet werden, können Sie ihn unverändert lassen

Das behebt auch andere Compiler-Probleme wie folgt:

  • Zu viele Initialisierungserrors für ein einfaches Array in bcc32

Wenn jemand ähnliche Probleme hat, hoffe das.

Schauen Sie sich auch einen pointers in C ++ Code mmap wenn Sie Ihre Speicherzuweisungen debuggen müssen ...