Hilfe beim Debugging: Tip benötigt
-
^
@CMatt: So richtig passt der Beitrag in keines der Foren. Es wird zwar der MS VC++ Compiler benutzt, er hat jedoch nichts mit C++ zu tun. Es ist nämlich eine reine C DLL.
-
Naja, ich würde sagen, es liegt eindeutig an myFunc
Deswegen wäre es gut, wenn du uns die mal zeigen würdest.
-
Hallo dEUs,
myFunc steht in einer 2. dll. Sie liest einfach eine Datei von der Festplatte in ein static struct ein. Das struct besteht unter anderem aus mehreren dynamisch angeforderten Arrays. Danach sucht myFunc je nach den Übergabeparametern in diesen Arrays und wirft das Ergebnis zurück. Dieses Ergebnis ist dann sowas wie 4.487e-8
Außerdem merkt sich myFunc das die Datei eingelesen wurde. Wenn ich jetzt myFunc ein zweites Mal aufrufe wird nur in den Arrays gesucht. Das Ergebnis das jetzt zurückgegeben wird, erscheint dann ohne Probleme in Excel.Den Code kann ich schlecht zeigen. Er schon etwas umfangreicher, außerdem "gehört" er nicht mir. Da Ihr in der Sache nicht drin steht würdet Ihr Stunden brauchen um herauszufinden worum es geht.
Meine Frage zielte mehr in die Richtung was ich prinzipiell noch überprüfen könnte. Die Rücksprungadressen werden nicht überschrieben. Es wird nicht über Arraygrenzen hinaus geschrieben... was könnte man noch machen?Ich habe mal irgendwas gelesen das wenn man dynamischen Speicher zwischen dll's austauscht man eventuell Probleme kriegen könnte. ICh weiß aber nicht mehr worum es da geht.
Viele Grüße
Mike
-
Mike Fudd schrieb:
könnte. Die Rücksprungadressen werden nicht überschrieben. Es wird nicht über Arraygrenzen hinaus geschrieben... was könnte man noch machen?
Du könntest beispielsweise einen Breakpoint in myFunc setzen und mal mit dem Debugger rüberschauen.
Mike Fudd schrieb:
Ich habe mal irgendwas gelesen das wenn man dynamischen Speicher zwischen dll's austauscht man eventuell Probleme kriegen könnte. ICh weiß aber nicht mehr worum es da geht.
Wenn Du den Speicher von unterschiedlichen Heaps allocierst, knallt es bei der Freigabe. Der Austausch des Speichers selbst ist kein Problem. Das betrifft Dich aber sowieso nicht, da Du lediglich einen double zurücklieferst.
BTW: Wie sieht denn das Merken des Arrays aus? Wird das auch irgendwo wieder feigegeben? Wenn ja, wo? Passiert das in DllMain? Wenn ja, hast Du die CRT statisch gelinkt?
-
Hallo King,
den Merker setze ich schon seit Tagen in die verschiedenen Funktionen und jage durchs Programm. Ich gehe von Schritt zu Schritt und sehe zu wie Daten in die Struktur gefüllt werden;-) Daran liegt es nicht.
Die Struktur an sich wird überhaupt nicht mehr freigegeben. Es handelt sich um eine statische Variable in myFunc.Code von dllMain wo myFunc drinsteht:
char *root=0; HANDLE hDllHandle=0; char *dllPath=0; // Dll Einstiegspunkt. BOOL APIENTRY DllMain( HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) { switch (ul_reason_for_call) { case DLL_PROCESS_ATTACH: break; case DLL_THREAD_ATTACH: break; case DLL_THREAD_DETACH: break; case DLL_PROCESS_DETACH: break; } hDllHandle = hModule; init(); return TRUE; } // Die Pfadvariablen setzen void init() { int i=0; char *tmp=0; // Den Pfad+Namen der dll abspeichern. tmp=(char *)malloc(4101); GetModuleFileName((HINSTANCE__ *)hDllHandle, tmp, 4100); i=strlen(tmp); dllPath=(char *)malloc(++i); memcpy(dllPath, tmp, i); free(tmp); // Den Pfad zum Verzeichnis eine Ebene Tiefer abspeichern. while (dllPath[--i]!='\\'); while (dllPath[--i]!='\\') { if (i==0) { // Falls "C:\", wieder zum ersten \ gehen. while (dllPath[++i]!='\\'); break; } } i=i+2; root=(char*)malloc(i); memcpy(root, dllPath, i); root[i-1]='\0'; }Es werden nur Pfadvariablen gesetzt, mehr nicht.
Viele Grüße
Mike
-
Wenn ich mal myFunc von dem unwichtigen Gerümpel befreie sieht sie so aus:
// Errechnung des Rückgabewertes. Bei Fehler INFINITY. extern ABCDLL_API double myFunc(double a, double b) { static int alreadyLoaded=0; // Marker ob File schon geladen. static struct myData *data=0; // Die Struktur. int retval=SUCCESS; double c=0; // File nur einmal laden. if (alreadyLoaded==0) { retval+=nothingLoaded(&data, "File.txt"); // Daten aus Datei laden if (retval==SUCCESS) alreadyLoaded=1; // Wenn kein Fehler! } // Ergebnis nur berechnen wenn Datei geladen. if ((data != NULL) && (retval==SUCCESS)) { retval=errechne(data, b, a, &c); if (retval==SUCCESS) { return c; } else { return log(0); } } else { return log(0); } }Kommentiere ich den Funktionsaufruf von "nothingLoaded(&data, "File.txt");" aus, passiert kein Fehler. Gleiches beim zweiten Aufruf, da die Datei schon geladen wurde.
-
Mike Fudd schrieb:
Es werden nur Pfadvariablen gesetzt, mehr nicht.
Aber aus DllMain heraus. Das funktioniert nur dann sicher, wenn Du die CRT statisch linkst. Machst Du das?
BTW: Der erste Parameter von DllMain ist nicht HANDLE, sondern HINSTANCE. Damit kannst Du dann Deiner globalen Variablen auch den richtigen Datentypen verpassen und kannst in der Init-Funktion auf diesen fürchterlichen cast verzichten.
-
Mike Fudd schrieb:
Kommentiere ich den Funktionsaufruf von "nothingLoaded(&data, "File.txt");" aus, passiert kein Fehler. Gleiches beim zweiten Aufruf, da die Datei schon geladen wurde.
Das verstehe ich nun gar nicht. Du sagst doch in Deinem Kommentar, daß die Datei in 'nothingLoaded' geladen wird. Wie kann die Datei beim zweiten Aufruf geladen sein, wenn Du die Zeile auskomentierst?
-
Ich meinte wenn ich den Funktionsaufruf "nothingLoaded(&data, "File.txt");" ganz auskommentiere gibt es keinen Fehler mehr.
Lasse ich den Aufruf drinnen passiert beim ersten Durchgang folgendes wenn ich mit F10 Schritt für Schritt durchgehe:
Im ersten IF Statement wird die Datei ohne irgendwelche Fehler in die Struktur data geladen.
Im zweiten IF Statement wird ganz normal ein Wert wie 4,78944e-8 errechnet. Dieser Wert steht in c.
Die Funktion wird via "return c;" verlassen. In c steht immer noch diese Zahl. Zurück in Excel erscheint dann die div/0 Fehlermeldung.Rufe ich in Excel die Funktion erneut auf wird in das erste IF Statement gar nicht mehr gesprungen. Diesmal wird wieder 4,78944e-8 errechnet. Dieser Wert erscheint dann auch in Excel...
Ersetze ich "return c;" durch "return 3;" passiert etwa das Gleiche: Beim ersten Aufruf erscheint die div/0 Meldung, obwohl ich nur 3 zurückgebe. Beim zweiten Aufruf erscheint dann die 3.Was ist CRT? Die Bibliothek wird als Lib ins Projekt eingebunden. Während der Compilezeit. Also statisch.
Der erste Parameter von DllMain ist nicht HANDLE, sondern HINSTANCE
Aber das Visual Studio hat dllMain so erstellt?
-
Mike Fudd schrieb:
Was ist CRT? Die Bibliothek wird als Lib ins Projekt eingebunden. Während der Compilezeit. Also statisch.
Das sind die C-Runtimes. Wenn Du da ohne Dll auskommst, ist's gut.
Aber das Visual Studio hat dllMain so erstellt?
Na und? Davon wird's nicht richtiger ...
Schau Dir den Link wenigstens an. Jedenfalls ist ein HANDLE in der Regel ein Kernel-Object, nicht aber ein Instanzen-Handle. HMODULE hätte ich mir auch noch gefallen lassen, HANDLE ist aber definitiv falsch.
Wenn ich Dich diesmal richtig verstanden habe, sitzt Dein Fehler entweder in 'nothingLoaded' oder in 'errechne' (auch letztere Funktion wird nicht mehr aufgerufen, wenn 'nothingLoaded' auskommentiert wird, da 'data' NULL bleibt).