Nochmal zu meinem Problem



  • Wie der muss aufgerufen werden? Ich denk, wenn meine abgeleitete Klasse keinen Destruktor implementiert, wird automatisch der von der Basisklasse aufgerufen, oder? 😕

    Und selbst wenn, dann dürfte doch keine Debug Assertion Failed kommen, höchstens ein Memory Leak, oder?

    ChrisM



  • ... dann wird automatisch ein destruktor gemacht, der den basisklassendtor aufruft.
    du darfst nur nirgends nach std::string casten und das dann löschen. dann müsste der basic_string dtor virtuell sein.
    also wenn du nur mit CString arbeitest, dann wird immer der dtor von basic_string aufgerufen werden (wenn du bei nicht-auto variablen immer brav delete-st)





  • @davie: Wie du ja am Code oben siehst, verwende ich nirgends std::string, sondern durchgehend CString. Ich versteh das einfach nicht. 😞

    ChrisM

    PS: Den Link les ich mir gleich mal durch, aber jetzt frühstück ich erstmal 🙂



  • Ich glaub, ich probiere jetzt mal STLport aus, mit der gehts evtl.
    Weiß jemand, wo ich STLport vorkompiliert für VC6 herkriege, weil ich nicht nmake'n kann, weil ich dummerweise keine Environment Variablen habe setzen lassen (bei der Installation von VC6)?

    ChrisM



  • schonmal was von absoluten pfadangaben gehört?

    naja, egal.
    das problem kann nicht an CString liegen - denn das einzige was sein kann ist, dass ein memory leak entsteht - aber sicher kein undefiniertes verhalten.

    ich nehme an, das problem liegt bei der übergabe der exception von der dll in die exe -> soweit ich weiß, ist soetwas böse. da eine exception in der dll eine andere signatur haben kann als in der exe.

    wirf mal eine exception in der exe und fang sie in der exe - ich wette es wird alles gut gehen.

    also ab damit in VC++ Forum 🙂



  • Nein, es geht auch in der EXE nicht. 😞

    void Test(const CString &String)
    {
        throw 1;
    }
    
        try
        {
            ::Test("Hallo");
        }
        catch (...)
        {
            MessageBox(NULL, "Unknown exception occured!", "Error", MB_ICONERROR | MB_OK);
        }
    
    // Hierher kommt das Programm nicht ohne die Debug Assertion!
    

    Der Debugger zeigt an:

    HEAP[Techdemo.exe]: Invalid Address specified to RtlValidateHeap( 00970000, 008600E0 )
    Nicht abgefangene Ausnahme in Techdemo.exe (KERNEL32.DLL): 0xE06D7363: Microsoft C++ Exception.

    Mögliche Erklärung, weiß aber nicht, ob sie stimmt: Die EXE erstellt das Objekt auf ihrem Heap, aber die DLL versucht es zu löschen, weil CString in der DLL implementiert ist. Da die Heaps getrennt sind, kommt dann die Assertion.
    Ich frag mich nur, warum nicht versucht wird, dass ganze von der EXE löschen zu lassen, ich hab ja in der DLL keinen Destruktor explizit erstellt. 😞

    ChrisM



  • *heul*

    Das kann doch net, verwend ich halt doch Multithreaded DLL Laufzeitbibliothek.

    Nur noch eine Frage, unter VC wird bei Multithreaded DLL ja die Standardbibliothek nicht direkt zur EXE gelinkt, sondern zur Laufzeit aus msvcrt.dll (Microsoft Visual C++ Runtime oder so).
    Die Frage ist nur, gibts sowas auch unter Linux, weil wenn nur wegen so einem Problem mein Programm nicht mehr unter Linux geht, wär das extrem ärgerlich!! (vielleicht dann als gccrt.so oder so ähnlich 🙂 )

    ChrisM



  • weg damit ins Linux Forum



  • Kein Problem, ich frag dort nach 🙂

    ChrisM



  • Original erstellt von ChrisM:
    **Nein, es geht auch in der EXE nicht. 😞

    void Test(const CString &String)
    {
        throw 1;
    }
    
        try
        {
            ::Test("Hallo");
        }
        catch (...)
        {
            MessageBox(NULL, "Unknown exception occured!", "Error", MB_ICONERROR | MB_OK);
        }
    
    // Hierher kommt das Programm nicht ohne die Debug Assertion!
    

    ChrisM**

    Kann es sein das die Exceptions ( (/EHsc) ) garnicht an sind ?



  • Doch, sind in den Compilereinstellungen aktiviert.

    Außerdem gehts ja ohne den CString-Parameter einwandfrei.

    ChrisM



  • Mach mal ein minimalbeispiel bei Dir (Win32 App und bau die Zeilen von oben ein) fliegt Dir hier immer noch eine Exception um die Ohren ?

    Das Problem scheint mir in der Methode zu sein die den CString bekommt.

    Gruß
    Michael



  • Mach ich, dauert aber noch etwas. 🙂

    ChrisM



  • So, ist hochgeladen.
    Hier könnt ihr euch ein minimales Testprojekt runterladen, in dem der Fehler auftritt:
    http://www.chrismandery.de/exptest.rar

    Falls ihr rar net öffnen könnt, sagt es grad nochmal und ich mach zip, dann wirds allerdings etwas größer (um 300kb).

    ChrisM



  • Oh man, da sseh ich jetzt erst, das Du CString von std::string erben lässt. Dabei stehts am Anfang 🤡

    Sorry, blind muss man sein. (CString gibts im VC halt auch, deswegen dacht ich Du verwendest diesen auch, mit dem klappte das ja auch super ;o).

    std::string hat keine virtuellen Methoden. Daher ist dieser nicht fürs Vererben geeignet. (z.B. Destruktor, so genau weiß ich die Argumente nicht. Aber in den newsgroups findest Du da was: http://groups.google.de/groups?hl=de&lr=&ie=ISO-8859-1&q=std%3A%3Astring+erben

    Das Hauptproplem:

    CString gibt es bereits! Der Compiler verwendet mal dies mal das.
    Benenne mal CString in eine Klasse um die es noch nicht gibt (C<Klasse> ist bei VC üblich für interna) und Du siehst: Es geht.

    Setz nen Breakpoint in den Konstruktor, Du wirst sehen: Da gibts kein Aufruf für. Es wird also ein ganz anderes CString zerstört wie Du in der Routine annimmst.

    Gruß
    Michael

    P.s.: Noch mal sorry das ich es zu spät gesehen hab wegen vererbung vom std::string 😇



  • Ja, ich weiß, dass es CString schon in den MFC gibt, aber wie kann der Compiler das MFC-CString verwenden, wenn ich ausdrücklich dem Linker sage, dass er die MFC nicht linken soll?

    Und das mit den nicht-virtuellen Funktionen dürfte ja nichts machen, weil ich ja explizit CString übergebe, d.h. es wird auch der CString-Destruktor aufgerufen (bzw. sollte er).

    ChrisM



  • fliegt dir die exception auch bei std::string um die ohgren, wenn nein, dann nenne CString mal um (wie du siehst hast du damit bereits die ersten Leute verwirrt).



  • Es passiert folgendes (theorie 🤡

    Der Compiler sieht den CString aus der ATL oder MFC (weiß nich so genau).
    Er schaut sich den Bauplan an und verwendet diesen auch fleissig.

    Der Linker dagegen sucht nur nach irgendetwas das CString heisst. Der Typ ist uninteresannt. Da der Linker die MFC nicht bekommt wird er im String.obj fündig und verwendet dieses.

    Du übergibst dort ein völlig anderes Objekt als Du vermuten würdest.

    Benenn mal den String um und Du wirst ggf. ncoh Probleme mit den Namesapces finden. (String.cpp - der kram muß noch in den NameSpace rein).

    Also: Mal umbenennen ;o) Und schau Dir mal den Link aus den NewsGroups an, von string zu erben war keine so gute Idee, ich kenn die gründe aber nicht mehr. Schaus Dir an damit Du weisst was es an Problemen geben könnte.



  • mfc ist doch garnicht eingebunden 😡


Anmelden zum Antworten