FreeLibrary() löst Fehler aus !?



  • ich lade in meinem programm eine DLL über 'LoadLibrary()'.

    die DLL ist in einer klasse verpackt die das aufrufen von funktionen innerhalb der DLL vereinfachen soll. im kontruktor dieser klasse wird 'LoadLibrary()' aufgerufen. dann erscheint eine Debug Assertion:

    dbgheap.c, line 1175.
    Expression: pHead->nBlockUse == nBlockUse
    

    das ist nicht das erste mal das ich DLLs in meinen programmen benutze, deshalb wundere ich mich über den fehler.

    zu meinem programm:

    es ist ein dialogfeldbasierendes programm, aus dem ich aber das dialogfeld entfernt habe. die dll wird in CWinApp::InitInstance() meiner anwendung geladen. innerhalb von InitInstance() lasse ich aus der DLL einen dialog anzeigen, der vom benutzer geschlossen wird. am ende meiner InitInstance() wird das programm beendet. im destruktor meiner 'DLL-verpackungs-klasse' wird FreeLibrary() ausgeführt.

    weis jemand einen rat ?

    EDIT:
    Wenn ich das Dialogfeld in der DLL nicht aufrufe, kann ich die DLL problemlos schließen



  • bin zwar immer noch nicht weiter gekommen, aber vielleicht hilft es zu wissen, dass der fehler auftritt sobald das dialogfeld-objekt aus dem speicher entfernt wird.

    ich habe das dialogfeld mal mit 'new()' erzeugt, als ich es mit 'delete' entfernen wollte kahm sofort der selbe fehler.



  • Vielleicht allokierst Du den Dialog in einer DLL und gibst Ihn in der EXE (oder einer anderen DLL) frei. Dabei hast Du wohl vergessen die CRT als DLL zu verwenden.



  • also der dialog wird direkt vom dialog her durch benutzereingabe geschlossen. also noch innerhalb der DLL.

    Jochen Kalmbach schrieb:

    Dabei hast Du wohl vergessen die CRT als DLL zu verwenden.

    das hab ich nicht ganz verstanden 😉 ich habe das dialogfeld doch in der DLL !?



  • Schau doch mal nach, wie der Callstack aussieht, wenn der Fehler auftritt!

    Wenn man über DLL Grenzen hinaus Speicher allokiert und woanders freigibt, so muss man sicherstellen, dass man die *gleiche* CRT (als DLL) verwendet.

    Aber das wichtigeste wäre mal den Callstack zu wissen!



  • ich konnte das problem jetzt lösen, aber nicht ganz sauber:

    ich habe mal nach CRT gegoogled und bin da auf nen interessantes gestossen: VirtualFree() / VirtualAlloc().

    ich gebe den speicher jetzt so frei:

    VirtualFree(xTest, 0, MEM_RELEASE)
    

    habe ihn aber nicht mit 'VirtualAlloc()' sondern mit 'new' allokiert.



  • Schlechte idee... zeig mal den Callstack!



  • das ist der neue code, wo der fehler ausbleibt:

    >	XT Engine.dll!RunXTEngine()  Zeile 158	C++
     	BXT.exe!CXTEngineDLL::RunXTEngine(int * iResult=0x0012fdcc)  Zeile 103 + 0x8	C++
     	BXT.exe!CBXTApp::InitInstance()  Zeile 72 + 0x12	C++
     	BXT.exe!AfxWinMain(HINSTANCE__ * hInstance=0x00400000, HINSTANCE__ * hPrevInstance=0x00000000, char * lpCmdLine=0x00141f1f, int nCmdShow=1)  Zeile 39 + 0xb	C++
     	BXT.exe!WinMain(HINSTANCE__ * hInstance=0x00400000, HINSTANCE__ * hPrevInstance=0x00000000, char * lpCmdLine=0x00141f1f, int nCmdShow=1)  Zeile 25	C++
     	BXT.exe!WinMainCRTStartup()  Zeile 251 + 0x30	C
     	kernel32.dll!7c816d4f() 	
     	ntdll.dll!7c925b4f() 	
     	kernel32.dll!7c8399f3()
    

    hier der code mit fehler:

    >	XT Engine.dll!_free_dbg_lk(void * pUserData=0x013e3650, int nBlockUse=1)  Zeile 1175 + 0x2b	C
     	XT Engine.dll!_free_dbg(void * pUserData=0x013e3650, int nBlockUse=1)  Zeile 1070 + 0xd	C
     	XT Engine.dll!free(void * pUserData=0x013e3650)  Zeile 1025 + 0xb	C
     	XT Engine.dll!FreeCObArray(CObArray * oArray=0x1014ebc0, int iIndex=-1, int bDeleteObject=1, int bUseFreeFnct=1)  Zeile 1085 + 0x12	C++
     	XT Engine.dll!CXTAnimation::ResetContent(int bBitmaps=1, int bSequences=1)  Zeile 233 + 0x12	C++
     	XT Engine.dll!CXTCharSetPreview::~CXTCharSetPreview()  Zeile 19	C++
     	XT Engine.dll!CXTEngineDlg::~CXTEngineDlg()  Zeile 54 + 0x8d	C++
     	XT Engine.dll!CXTEngineDlg::`scalar deleting destructor'()  + 0x2b	C++
     	XT Engine.dll!RunXTEngine()  Zeile 157 + 0x35	C++
     	BXT.exe!CXTEngineDLL::RunXTEngine(int * iResult=0x0012fdcc)  Zeile 103 + 0x8	C++
     	BXT.exe!CBXTApp::InitInstance()  Zeile 72 + 0x12	C++
     	BXT.exe!AfxWinMain(HINSTANCE__ * hInstance=0x00400000, HINSTANCE__ * hPrevInstance=0x00000000, char * lpCmdLine=0x00141f1f, int nCmdShow=1)  Zeile 39 + 0xb	C++
     	BXT.exe!WinMain(HINSTANCE__ * hInstance=0x00400000, HINSTANCE__ * hPrevInstance=0x00000000, char * lpCmdLine=0x00141f1f, int nCmdShow=1)  Zeile 25	C++
     	BXT.exe!WinMainCRTStartup()  Zeile 251 + 0x30	C
     	kernel32.dll!7c816d4f() 	
     	ntdll.dll!7c925b4f() 	
     	kernel32.dll!7c8399f3()
    


  • In "FreeCObArray" wird irgendwas freigegeben, was vorher nicht korrekt allokiert wurde.

    So wie es mir aber aussieht, besteht bei Dir die Gefahr, dass Du in der EXE was allokierst und in der DLL freigeben willst (nur eine Vermutung).

    Deshalb rate ich Dir dringend in der DLL und der EXE jeweils die (gleiche) DLL-Version der CRT zu verwenden. Dann wird der Fehler vermutlich weg sein.



  • Jochen Kalmbach schrieb:

    Deshalb rate ich Dir dringend in der DLL und der EXE jeweils die (gleiche) DLL-Version der CRT zu verwenden. Dann wird der Fehler vermutlich weg sein.

    ich habe versucht 'multithreaded-DLL' zu benutzen, es traten aber ein par fehlermeldungen auf beim kompilieren (LNK2001). konnte aus der msdn ein bischen über CRT in erfahrung bringen. mit der LIBCMT.LIB bibliothek konnte ich DLL und applukation kompilieren. es trat aber ein fehler beim aufruf von DoModal() meines dialogfeldes auf !?

    bisher habe ich es mit 'Multithreaded' gemacht, was dann nach 'VirtualFree()' geklappt hat.

    benutze ich da eine falsche lib o.ä. ?



  • ich weis jetzt woran es liegt, kann es mir aber nicht erklären:

    ich habe durch zufall gerade an einem andern projekt gearbeitet, indem ich eine klasse verwende, die ich auch in der DLL benutze. das programm hat aber nichts mit der DLL zu tun.

    ich benutze in dem programm keine libs o.ä. fremdes. es kommt aber jetzt der selbe fehler wie in der DLL, der nach dem aufruf von delete erscheint.

    das objekt, bei dem der fehler beim delete kommt erzeuge ich so:

    CXTSequence xSeqTmp = new CXTSequence();
    CFile fFile;
    
    fFile.Read(xSeqTmp, sizeof(CXTSequence));
    

    das auslesen aus der datei dürfe doch nicht den fehler verursachen, oder ? anderes wird aber nicht mit dem objekt gemacht.



  • Das Problem ist, dass in der EXE Speicher allokiert (z.B. via CFile.Read) wird der in der DLL wieder freigegeben wird!!!
    Das ist *nur* dann zulässig, wenn die DLL und die EXE die gleiche (shared) CRT verwenden!!!
    Also Du *musst* die DLL und die EXE mit der gleichen DLL-version der CRT linken!



  • ich benutze doch schon die selbe CRT. aber das problem tritt doch auch im programm ohne die DLL auf.

    daher muss das problem ja woanders liegen, oder siehst du das anders ?



  • Dann mach mal ein "MInimalprogramm" wo der Fehler aufritt und mail sie mir zu 😉



  • ich habe gerade das "miniprogramm" gebastelt und es lief. zum testen hatte ich einfach nur ein objekt erzeugt, in ein CObArray gepackt und die klasse in der das CObArray enthalten ist gelöscht.

    daraufhin habe ich meine unbearbeiteten klassen (hatte die ja für das miniprogramm geändert) ins programm eingebunden und es lief auch. dann habe ich das im test erzeugte objekt über CFile eingelesen (also speicher erzeugt und mit CFile::Read() die infos aus der datei im objekt gespeichert). dann trat der beschriebene fehler auf.

    ich hoffe die fehlerbeschreibung hilft auch weiter, da die abgespeckte version nichts nützen würde. ich kann mir den fehler aber nicht erklären, da ich doch den speicher selbst erzeuge, und er doch nur von CFile benutzt wird !?



  • Ist CXTSequence eine "Klasse" oder ein POD? PODs kannst du so schreiben/lesen wie du das machst (solange sie keine Zeiger/Handles/... enthalten), "echte Klassen" nicht.



  • CXTSequence ist eine klasse, die enthält nur zwei variablen (keine handles ö.ä.) und eine funktion.

    dann muss ich das wohl anders machen mit dem einlesen. danke für die hilfe !! dann weis ich jetzt weiter 😉


  • Mod

    Red Skall schrieb:

    ich habe gerade das "miniprogramm" gebastelt und es lief. zum testen hatte ich einfach nur ein objekt erzeugt, in ein CObArray gepackt und die klasse in der das CObArray enthalten ist gelöscht.

    daraufhin habe ich meine unbearbeiteten klassen (hatte die ja für das miniprogramm geändert) ins programm eingebunden und es lief auch. dann habe ich das im test erzeugte objekt über CFile eingelesen (also speicher erzeugt und mit CFile::Read() die infos aus der datei im objekt gespeichert). dann trat der beschriebene fehler auf.

    ich hoffe die fehlerbeschreibung hilft auch weiter, da die abgespeckte version nichts nützen würde. ich kann mir den fehler aber nicht erklären, da ich doch den speicher selbst erzeuge, und er doch nur von CFile benutzt wird !?

    Dumusst in jedem Fal den Serialisierungsmechanismus der MFC verwenden. Was sind das für Objekte und wie schreibst Du sie. Es geht in keinem Fall einfach. das Objekt einzulesen und gnadenlos das Speicherimage zu überschreiben. Da gehenja die vtable Pointer flöten...



  • also ich erzeuge die CXTSequence-objekte mit new und schreibe sie über CFile::Write() in die datei:

    CObArray oSequences;
    	CXTSequence *xSequenceTmp;
    	CFile fFile;
    
    	// Sequenzen in Datei schreiben:
    	for (INT_PTR u = 0; u < oSequences.GetCount(); u ++)
    	{
    		xSequenceTmp = (CXTSequence*) oSequences.GetAt(u);
    
    		fFile.Write(xSequenceTmp, sizeof(CXTSequence));
    	}
    

    die klasse ist wie folgt aufgebaut:

    class CXTSequence : public CObject
    {
    public:
    					CXTSequence													();
    					CXTSequence													(INT_PTR iBMPIndex, int iFrames);
    
    public:
    	void			operator =													(CXTSequence &xSeq);
    
    public:
    	INT_PTR																		iBMPIndex;
    	int																			iFrames;
    };
    

    das das speicherimage nicht zu überschreiben ist leuchtet total ein. hatte serialisierung noch nie benutzt aber mich mal etwas eingelesen. du meinst ich soll das mit CArchive und Serialize() schreiben / lesen !?


  • Mod

    Und genau das geht nicht!
    Versteh doch das CObject kene pure Datenklasse ist. Da ist mindestens ein vtable Zeiger drin.

    Verwende die Serialze Funktion der CObject Klasse!



  • ich habe das doch schon verstanden 🙄. ich habe nur geschrieben wie ich gemacht habe, habe noch nicht weiter gemacht am programm.

    habt mir aber sehr weiter geholfen, danke euch !! 😉


Anmelden zum Antworten