Seite 1 von 2

[gelöst, die 2.] Seltsame Probleme mit DLL

Verfasst: 5. Februar 2010 15:37
von Kay
Hallo Leute,

Ich habe ein sehr seltsames Problem mit meiner DLL. Ich bin mittlerweile völlig verzweifelt und hoffe mir kann jemand helfen. Leider muss ich dafür etwas weiter ausholen...

Ich habe meine Matrizen-DLL endlich schön erstellen können und sie wurde auch geladen. Die ersten Tests verliefen anstandslos. Anfangs hab ich meine Matrix einfach als Wert übergeben, danach wollte ich einen Pointer darauf zurückgeben, um mir das ständige Kopieren zu ersparen. Die Daten für die Matrix kommen aus einer Datenbankklasse, die während der gesamten Programmlaufzeit existiert. Darin hab ich einen Matrixpointer, der beim Lesen von der Datenbank entsprechend der Anzahl der Daten mittels new() ein Matrixobjekt zugewiesen bekommt. In das Objekt schreibe ich meine Daten und gebe schließlich den Pointer auf die Matrix zurück.

Mein Problem ist, dass jeder Zugriff auf die Matrix über den zurück gegebenen Pointer zum Programmabsturz führt. Wenn ich das Programm normal starte (aus dem QtCreator) dann wird mir ein Fehlerdialog von Windows gezeigt (bei der Stelle mit dem Zugriff auf die Matrix über den Pointer). Anschließend kann ich die Stelle mit dem VisualStudio-Debugger im Disassembly ansehen. Als Fehlermeldung bekomme ich: "Zugriffsverletzung beim Lesen an Position 0xffffffff." Das Disassembly bleibt bei einem Zugriff auf die SSE-Register stehen.
Wenn ich das Programm aus dem QtCreator mittels des Buttons "Debug" starte, hängt sich das Programm ebenfalls bei dem ersten SSE-Befehl auf, was sich mit dem Disassembly aus dem VS deckt.

So nun zu den seltsamen Sachen: Im QtCreator-Debugger ist das Objekt auf das in den SSE-Intrinsics zugegriffen wird vorhanden! Die Pointer darauf sind richtig (habe die Adresse der Matrix aus der Datenbankverbindung verglichen) und die Objekte enthalten die richtigen Member. Trotzdem bleibt er beim ersten Zugriff auf das Quellobjekt (bei Kopierkonstruktoren bspw. aber auch bei anderen Operationen) in der entsprechenden Zeile stehen. Der SSE-Intrinsic-Code wird aber noch ausgeführt (zumindest der Teil in emmintrin.h).
Der Speicher ist aber aligned.
Die gesamte Matrixklasse und die dazugehörige Vektorklasse wurden ausgiebig mittels QtTest getestet. Sowohl als Dll als auch mit reinkompiliert und haben funktioniert.
Kompiliere ich mein Programm und die Bibliothek im Release-Modus tritt der Fehler ebenfalls nicht auf. Und wenn ich das Programm unter Linux kompiliere und starte kommt es ebenfalls nicht zu einem Fehler. Somit sind (einfache) Programmierfehler schon mal ausgeschlossen und ich tippe auf einen Zusammenhang zwischen Windows und dem Erzeugen der Library / Linken.

Hat irgendjemand eine Idee, wodurch dieses seltsame Verhalten hervorgerufen wird? Selbst wenn ich die Matrixklasse mit in das Programm kompiliere, statt es zu linken?

Ein Freund von mir, der hauptsächlich C# programmiert, meint, dass Windows öfter mal Sachen im Speicher verschiebt. Ich kann mir vorstellen, dass sowas zu dem oben beschriebenen Phänomen führt. Bin mir aber nicht sicher, ob das auf Qt-Programme zutrifft und wie man dieses Verschieben verhindert. In C# gibts dafür den "fixed" Befehl, aber sowas gibt es ja nicht unter MinGW.

Bin für jede Idee dankbar, da ich mittlerweile echt am Verzweifeln bin.

Grüße,
Kay

Verfasst: 5. Februar 2010 16:34
von Christian81
Wenn es crasht liegt es wohl an einem Programmierfehler in der Matrixklasse... aber ohne Code bzw. Testcase zum Reproduzieren - was sollen wir da machen?

Verfasst: 5. Februar 2010 18:25
von Kay
Ich bin mir sehr sicher, dass es nicht an einem Programmierfehler der Matrixklasse liegt. Die wichtigsten Funktionen konnte ich ja von nem Buch entnehmen und die Memberfunktionen sind wie gesagt alle getestet.
Mit Codebeispielen wird es auch etwas schwierig, da das Problem wirklich erst in der gesamten Software auftritt und das etwas zu viel zum Posten ist.

Ein Programmierfehler in der Matrixklasse scheint mir auch unwahrscheinlich, da das Programm ja unter Linux und im Release-Modus in Windows anstandslos funktioniert. Dementsprechend sind strukturelle Fehler im Quellcode doch eigentlich auszuschließen, oder? Ich tippe in dem Fall wirklich auf eine Besonderheit beim Linken/Kompilieren von DLL und Programm unter Windows im Debugmodus.

Ich werde aber mal versuchen, ein Minimalbeispiel zu erzeugen, bei dem der Fehler auftritt. Vielleicht hat inzwischen ja noch jemand ne Idee?

Grüße,
Kay

Verfasst: 5. Februar 2010 18:31
von Christian81
Wenn es unter Linux läuft -> valgrind

Verfasst: 5. Februar 2010 18:33
von Kay
Bin gerade dabei. Kannst du mir dafür ein graphisches Frontend zur Darstellung der Ergebnisse empfehlen?

Verfasst: 5. Februar 2010 19:03
von Kay
Also ich habe jetzt mittels Alleyoop (Valgrind-Frontend...?) mein Programm durchlaufen lassen. An der entscheidenden Stelle, wo es in Windows abstürzt gibt es keine Meldungen. Nur vorher, aber die sind alle nicht aus meinem Code... (sondern libX11 und libQtGui und so)
Danach gibt es erst eine weitere Meldung nach dem Schließen des Programms. Weil ich prüfe ob ein Pointer auf NULL zeigt und er vorher nicht benutzt wurde (uninitialised value). Aber das ist beabsichtigt...

Gibt es sowas wie Valgrind denn für Windows?

Verfasst: 5. Februar 2010 20:09
von Christian81
Dann hilft wohl nur unter Windows ordentlich debuggen.

[quote]
Weil ich prüfe ob ein Pointer auf NULL zeigt und er vorher nicht benutzt wurde (uninitialised value). Aber das ist beabsichtigt...
[/quoe]
Das ist doch hoffentlich nicht dein Ernst, oder??

Verfasst: 5. Februar 2010 20:20
von Kay
Wie würdest du das denn machen, wenn du Pointer hast, die du vielleicht brauchen könntest? Für jeden ein Flag einzurichten wäre doch sehr umständlich. So initialisiere ich den Pointer mit NULL und wenn ich ihn dann mit new initialisiere, ist er ja nicht mehr NULL und ich kann ihn löschen. Ich glaube Valgrind nimmt das Initialisieren mit NULL nicht so ernst und denkt dann der Pointer ist uninitialisiert, weil er ja nie ein new() gesehen hat, wenn ich ihn nicht gebraucht habe. Oder?

Mit was würdest du unter Windows debuggen? Gerade wo ich ja mit dem QtCreator und MinGW arbeite und mir somit der VS-Debugger nicht zur Verfügung steht.
Wie gesagt, beim schrittweise Prüfen des Codes kam mir nichts verdächtig vor.

Verfasst: 5. Februar 2010 20:34
von Christian81
Wenn du de Pointer mit NULL initialisierst dann meckert valgrind nicht. Wenn valgrind meckert dann hat es (vor allem in solchen Fällen) zu 99.99% Recht. D.h. entweder hast du vergessen mit NULL zu initialiseren oder da it was anderes faul.
Und eine "delete 0;" ist erlaubt - da braucht man nicht prüfen.

Zu Deinem eigentlichen Problem: ich würde erstmal einfach eine simple Funktion in die DLL einbauen und aufrufen und diese so lange erweitern bis es crasht. Oder eben umgedreht - solange die Funktion vereinachen bis es nicht mehr crasht.

Verfasst: 5. Februar 2010 21:14
von Kay
Ok, mit dem "uninitialised value" hatte Valgrind recht. Ich hatte noch einen zweiten Konstruktor geschrieben, der einen der Pointer gleich mit initialisiert, den anderen aber nicht auf NULL setzt. Danke, hätt ich ohne dein Drängen erstmal nicht nachgeschaut.
Jetzt bekomme ich nur noch Fehler angezeigt in Modulen, die ich nicht geschrieben habe. Ist das normal?

Ich werde wohl versuchen bei meinem Programm erstmal klein anzufangen und wieder immer mit rein zu nehmen. Ich bin mir wie gesagt doch recht sicher, dass es nicht die Library ist. Die hab ich wirklich viel getestet.

Verfasst: 5. Februar 2010 21:18
von Christian81
Das valgrind in anderen Modulen Fehler (meist 'use of uninitialized values') anzeigt ist (leider) normal. Teilweise ist es aber auch nicht wirklich tragisch.
Gut zum Entdecken von memleaks wäre noch 'valgrind --leak-check=full'. aber auch dort wirst Du einige 'Fehler' in Qt sehen. Wobei hier valgrinds Aussagen nicht immer richtig sind - aber zum groben Überblick ist es nicht schlecht.

Verfasst: 7. Februar 2010 12:04
von Kay
Hi,

Also ich habs jetzt geschafft, mein Qt-Projekt unter VisualStudio mit Qt 4.3 (statt wie bisher 4.5) zu compilieren.
Ich habe nur nicht Qwt mit einbebaut, da ich es nicht auch erst noch für Visual Studio compilieren wollte.
Jedenfalls klappt hier die entscheidende Stelle natürlich wieder problemlos. :/ Keine Fehlermeldung wie vorher... Habs als Debug laufen lassen.
Ich hatte gehofft, dass ich mit dem VS-Debugger dem Problem auf den Grund gehen könnte, aber da es nicht auftritt, kann ich es schwer debuggen.

Kann es denn an der Größe des Programms im Speicher beim Ausführen liegen? Wie könnte man das rausfinden? Einfach die Release-Variante so lange weiter programmieren, bis sie auch so groß wird, dass sie sich aufhängt? Und wenn das nicht klappt?

Verfasst: 7. Februar 2010 12:12
von Christian81
Also das es am Speicherverbrauch hängt glaube ich nicht. 2GB wollen schon gefüllt sein. außerdem kann man sowas schön im Task-Manager anschauen.
Wenn du es eh mit VS kompileirt bekommt - warum dann nicht gleich immer vs bentuzen?
Mal versucht die MinGW-Variante ohne Qwt zu benutzen? Vielleicht ligts ja daran...

Verfasst: 7. Februar 2010 15:28
von Kay
Den Speicherverbrauch hab ich nicht gemeint. Nur das Speichermanagement, das halt ab nem bestimmten Maß eingreift...

VisualStudio bietet sich nicht so an, da ich die Software im Rahmen meiner Masterarbeit bei einer Firma schreibe. Wichtig dabei ist den Preis im Rahmen zu halten (umsonst...!?) und möglichst wenig Lizenzprobleme zu erzeugen. Abgesehen davon wird viel Wert auf Plattformunabhängigkeit gelegt. Deshalb bietet sich MinGW an, da der dem gcc auf Linux ja doch ähnlicher ist als der VS-Compiler.

Habe jetzt das VS-Projekt ohne Qwt wieder in ein Qt-Pro-File wandeln lassen. Vielleicht liegt das Problem ja an den Einstellungen.... Aber Pustekuchen! In dem Qt-Projekt tritt das Problem wieder auf. Beim selben Quellcode!
Auch das unveränderte Projekt stürzt ab, wenn ich Qwt raus nehme.

Das Problem scheint für mich beim Linker oder Compiler zu liegen. Bzw an deren jeweiligen Optionen...???

So langsam gehen mir die Ideen aus... Hast hier jemand noch welche?

Verfasst: 7. Februar 2010 16:23
von Christian81
Ist es Qt 4.6 oder 4.5? Bei 4.5 war noch gcc 3.4 dabei. Bei 4.6 gcc 4.4.0. Evtl. ists ein Compilerproblem.
Aktuelle Linker und Compiler gibts unte sf.net/projects/mingw (aktueller gdb, aktualisierte mingw-runtime,biutils, ...)

Aber wie gesagt - so lange abspecken bis es nicht mehr auftritt ist da wohl die einzigste Möglichkeit...