Invalid Address specified to RtlValidateHeap( 01C20000, 01EA09B8 )



  • hallo zusammen,

    ich bin völlig ratlos bei diesem Invalid Address specified to RtlValidateHeap( 01C20000, 01EA09B8 ) fehler.
    ich habe schon mehrere tage lang im internet gesucht und bin mir auch sicher, dass das problem daran liegt, dass ich ein objekt nicht in demselben heap lösche, in dem ich es erzeigt habe. das rätselhafte ist aber, dass ich das fragliche objekt in demselben objekt lösche, in dem ich es auch erstellt habe. müsste es dann nicht derselbe heap sein?

    dann habe ich erfolglos versucht, das objekt nur über objekt::NEW(){ return new objekt; } zu erstellen und über objekt::DELETE(objekt* ob){ delete ob; } zu löschen.

    ich weiß, dass ihr konkret nichts sagen könnt, wenn ihr den quellcode nicht seht. leider ist das projekt dermaßen komplex, dass ich es hier nicht posten kann.

    wie ist die vorgehensweise, um den fehler genauer zu bestimmen? ich habe z.b. testweise

    mal intptr_t hCrtHeap2 = _get_heap_handle();
    

    eingefügt, hat mich aber auch nicht nach vorne gebracht. wie kann ich z.b. herausfinden, in welchem heap ein objekt gelöscht werden muss?

    danke für eure ideen.



  • Vermutlich hast Du irgendwo Speicher überschrieben...



  • ok, danke.
    kann ich irgendwie herausfinden, wo das geschieht? kann ich eine art sensor einstellen, der mich warnt, wenn der speicherbereich den objektes überschrieben wird?
    ich arbeite mit visual studio 2008 pro auf win xp.



  • Debugging Tools for WIndows, dann dort den "Page Heap" für diesen Prozess aktivieren...



  • ok, vielen dank! eine neue welt des debuggens....

    nur habe ich mehr infos zu dem problem, stecke aber leider trotz internetrecherche weiter fest.

    ich habe jetzt bei den debugging tools für windows die kernel flags "enable application verifier", "enable heap tagging", "enable heap tagging by dll" und "enable page heap" aktiviert und bekomme folgende infos:

    ===========================================================
    VERIFIER STOP 00000008: pid 0xF50: corrupted heap pointer or using wrong heap

    03551000 : Heap used in the call
    0394C7D0 : Heap block
    00000044 : Block size
    03791000 : Heap owning the block

    wie bekomme ich nun heraus, welchen heap ich korrekterweise benutzen sollte? anders gefragt, wie kann ich feststellen, zu welcher dll der "heap owning the block" gehört?

    danke für die hilfe.



  • Das ist nicht ganz einfach...
    Wenn Du WinDBg verwendest 😉 , dann gib mal

    !heap -s

    ein.
    Das gibt dann z.B. sowas (sorry, 64-Bit):

    0:000> !heap -s
    NtGlobalFlag enables following debugging aids for new heaps:
    tail checking
    free checking
    validate parameters
    LFH Key : 0x000000e1623425c3
    Termination on corruption : ENABLED
    Heap Flags Reserv Commit Virt Free List UCR Virt Lock Fast
    (k) (k) (k) (k) length blocks cont. heap
    -------------------------------------------------------------------------------------
    00000000001f0000 40000062 1024 20 1024 1 1 1 0 0
    0000000000010000 40008060 64 4 64 1 1 1 0 0
    0000000000020000 40008060 1068 64 1068 61 1 1 0 0
    -------------------------------------------------------------------------------------

    Am einfachsten ist es rauszufinden, wenn Du den Prozess in WinDbg lädst, und dann einen Breakpoint in "HeapCreate" setzt...

    bp HeapCreate

    Und dann einfach startest... dann merkst Du Dir, wer welchen Heap erzeugt hat.... (Callstack kannst Du mit "kb" anschauen; weitermachen wieder mit "g").

    Siehe auchh:
    http://www.informit.com/articles/article.aspx?p=1081496



  • das hat mir alles super weiter geholfen, danke! nun habe ich auch für andere probleme weitere informationsquellen.

    zur lösung allgemein: es gibt bei wxWidgets unter windows wohl ein problem mit wxString in dlls. ich habe alle wxStrings aus meiner dll entfernt und alles war ok.


  • Mod

    Vermutung:
    Deine DLL und Deine EXE sind mit Sicherheit nicht mit der DLL Version der CRT gelinkt. Deshalb schmiert das ganze vermutlich ab, wel Du die Strings über DLL Grenzen hinweg übergibst und freigibst.



  • hi martin,

    du hast absolut recht, danke! ich hatte da etwas grundlegendes falsch verstanden.
    das problem ist gelöst.



  • Ich hatte das selbe Problem und auch beim freigeben eines Stringes und bin auf Eure Diskussion gestossen. Nach immer fast identisch 641,17 Sekunden hatte ich den Absturz beim freigeben eines Objektes, welches 2 Strings enthielt in der Freigabe der Strings. Ein Objekt dieser Klasse wurde da schon mehree tausend mal erzeugt und einige hundert Mal freigegeben.

    Ich habe dann vom Executable und allen Dlls die Compilereinstellungen geprüft. Diese waren identisch. Ich habe vor meinen new und delete Aufrufen den Heap überprüft und es wasr immer der gleiche.
    Alle delete Aufrufe waren immer in der gleichen DLL, in der auch das new für die Klasse stand. Ich benutze Fabriken um meine Objekte zu erzeugen, und jede Fabrik recycelt Ihre Objekte auch.
    Nach mehreren Tagen debuggen mit Betrachtung der Speicherbereiche um die Datenblöcke der Strings, ist mir aufgefallen, dass das Nomansland beim delete nicht mit 0xFDFDFDFD initialisiert war.

    Mittlerweile habe ich die Lösung des Problems gefunden. Eine abgeleitete Klasse hat im Konstruktor explizit den Konstruktor ihrer Superklasse aufgerufen. Da aber am Anfang im Konsruktionsprozess die Konstruktoren von der obersten Superklasse her zu konstruierten Klasse hin aufgerufen werden, führt das dazu, dass sich Konstruktoren im Kreis aufrufen. Dies hat dann einen Aufruf des Destruktors zuviel (bereits während der Konstruktion) zur Folge.

    Nachdem ich nun den expliziten Auftruf des Konstruktors das Superklasse entfernt habe, läuft es problemlos.


Anmelden zum Antworten