4 Stimmen

LoadLibrary schlägt fehl, wenn eine bestimmte Datei beim Erstellen der DLL eingeschlossen wird

Ich bekomme wirklich seltsames Verhalten in einer der DLLs meiner C++-App. Es funktioniert und lädt einwandfrei, bis ich eine einzige Datei in der Hauptdatei der DLL mit #include einbinde. Dann erhalte ich diese Fehlermeldung:

Komponenten werden aus D:/Targets/bin/MatrixWorkset.dll geladen Konnte "D:/Targets/bin/MatrixWorkset.dll" nicht laden: Kann die Bibliothek MatrixWorkset nicht laden: Ungültiger Zugriff auf Speicherort.

Jetzt habe ich den Code durchsucht und gegoogelt und kann nicht herausfinden, was passiert. Bis jetzt war alles in einer einzigen DLL, und ich habe beschlossen, es in zwei kleinere aufzuteilen. Die Datei, die die Probleme verursacht, gehört zur anderen zweiten Bibliothek (die problemlos lädt).

Über Ideen wäre ich wirklich dankbar. Vielen Dank, Jaco

0 Stimmen

Zeigen Sie etwas Code, ein #include kann alles tun.

0 Stimmen

OK, nach weiterem Debuggen. Die Datei (mit der Klasse MatrixVariable) muss nicht einmal in anderen Dateien enthalten sein. Ich muss sie einfach zum Makefile für die DLL hinzufügen, was die DLL zerstört. MatrixVariable erbt von einer Klasse innerhalb der zweiten DLL und das war es auch schon. Es hat funktioniert, als nur 1 DLL verwendet wurde.

6voto

MSalters Punkte 166675

Die wahrscheinliche Ursache ist ein globales Objekt mit Klassentyp. Der Konstruktor wird von DllMain() aufgerufen, und DllMain() wird wiederum ausgeführt, bevor LoadLibrary() zurückkehrt. Es gibt ziemlich viele Einschränkungen, was Sie tun können, bis DllMain() zurückgegeben hat.

1 Stimmen

"Es gibt ziemlich viele Einschränkungen, was Sie tun können, bis DllMain() zurückgegeben hat." ... wie zum Beispiel? Link bitte...

2voto

kevin42 Punkte 2108

Ist es möglich, dass der Header irgendwo eine #pragma comment(lib,"somelibrary.lib") Anweisung enthält? Wenn ja, versucht es automatisch, eine Bibliothek zu importieren.

Um dies zu beheben, würde ich damit beginnen, die Binärdatei mit depends (http://www.dependencywalker.com/) anzusehen, um zu sehen, ob es DLL-Abhängigkeiten gibt, die du nicht erwartest. Wenn du etwas findest und du dich in Visual Studio befindest, solltest du "Show Progress" bzw. /VERBOSE für den Linker aktivieren.

Da du den Fehler "Ungültiger Zugriff auf Speicheradresse" erhältst, besteht die Möglichkeit, dass etwas im DLLMAIN oder einem statischen Initialisierer abstürzt. Kannst du die MatrixWorkset.dll (angenommen, du hast sie geschrieben) vereinfachen?

0 Stimmen

Ich bin ziemlich sicher, dass es keine #pragma-Anweisung in der eingebundenen Datei gibt, da ich sie selbst geschrieben habe und sie funktioniert, wenn sie in einer anderen DLL verwendet wird, die sie auch verwendet. Im Abhängigkeitswalker sieht alles gut aus. Die nicht funktionierende DLL enthält eine Duplikatkopie der abhängigen DLL, was bei der funktionierenden DLL nicht der Fall ist.

0 Stimmen

Auch habe ich die MatrixWorkset.dll vereinfacht, bis sie funktioniert, wenn ich den Header nicht einschließe, und dann funktioniert sie. Ich habe diese funktionierende Kopie mit der nicht funktionierenden Kopie verglichen und die doppelte DLL ist der einzige Unterschied, den ich sehen kann...

0voto

veefu Punkte 2672

Der von Ihnen beschriebene Fehler klingt nach einem Laufzeitfehler. Wird dieser Fehler automatisch von Windows angezeigt oder wird er von Ihrem Programm ausgegeben?

Ich würde empfehlen, einen Debugger an Ihre Anwendung anzuhängen und zu verfolgen, woher dieser Fehler kommt. Kann es sein, dass Windows es nicht schafft, eine Abhängigkeit zu laden? Oder scheitert Ihre Bibliothek irgendwie beim Laden?

Wenn Sie dieses Header-Datei als Ursache ausschließen möchten, versuchen Sie, Ihre Hauptquelle sowohl mit als auch ohne dieses #include vorzukompilieren und vergleichen Sie die beiden Ergebnisse.

0voto

Ich komme immer noch nicht voran. Lassen Sie mich einige der gestellten Fragen beantworten:

1) Windows kann keine Abhängigkeit laden, ich denke, da Dependency Walker zeigt, dass alles in Ordnung ist. 2) Ich habe einen Debugger angehängt, der im Wesentlichen Folgendes ausgibt, wenn er versucht, MatrixWorkset.dll zu laden:

            10:04:19.234
stdout:&"warning: Loading components from D:/ScinericSoftware/VisualWorkspace/trunk/Targets/bin/MatrixWorkset.dll\\n"
            10:04:19.234
stdout:&"\\n"
status:Stopped: "signal-received"
status:Gestoppt.
            10:04:19.890
stdout:30\*stopped,reason="signal-received",signal-name="SIGSEGV",signal-meaning="Segmentation fault",thread-id="1",frame={addr="0x7c919994",func="towlower",args=\[\],from="C:\\\\WINDOWS\\\\system32\\\\ntdll.dll"}
input:31info shared
input:32-stack-list-arguments 2 0 0
input:33-stack-list-locals 2
input:34-stack-list-frames
input:35-thread-list-ids
input:36-data-list-register-values x
            10:04:19.890

3) MSalters: Ich bin mir nicht sicher, was Sie mit einem "global mit Klassentyp" meinen. Die Datei, die Probleme verursacht, wurde in einer anderen DLL inkludiert, in der sie einwandfrei funktionierte und erfolgreich geladen wurde.

Das ist der Anfang der Datei MatrixVariable.h:

#include "QtSF/Variable.h"   // Befindet sich in der abhängigen DLL (der DLL, in der diese Datei immer vorhanden war.
#include "Matrix.h"    // Datei befindet sich in dieser DLL
#include "QList"      // Dies sind alles Dateien aus dem Qt Framework
#include "QModelIndex"
#include "QItemSelection"
#include "QObject"

using namespace Zenautics;
using namespace std;

class MatrixVariable : public Variable
{
    Q\_OBJECT
    Q\_PROPERTY(int RowCount READ rowCount WRITE setRowCount)
    Q\_PROPERTY(int ColumnCount READ columnCount WRITE setColumnCount)
    Q\_PROPERTY(int UndoPoints READ undoPoints WRITE setUndoPoints)

public:
    //! Standardkonstruktor.
    MatrixVariable(const QString& name, int rows, int cols, double fill\_real = 0, double fill\_complex = 0, bool isReal = true);

etc. etc. etc.

Eine mögliche Lösung wäre, die MatrixVariable-Datei wieder in die ursprüngliche DLL zu verschieben, aber das widerspricht der Idee, die DLL in kleinere Teile aufzuteilen, was nicht wirklich eine Option ist.

0voto

Tim Punkte 19787

Ich erhalte diesen Fehler von GetLastError(), wenn es mir vor kurzem nicht gelingt, eine DLL von einem Befehlszeilen-EXE zu laden. Es hat zuvor funktioniert, dann habe ich einige MFC-Code zur DLL hinzugefügt. Jetzt ist alles mögliche passiert.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X