[solved] Dynamisch eingebundene DLL schmeißt exceptions.



  • Mr.Long schrieb:

    Sollte die V-Table nicht immer am selben Ort sein? Steht doch bestimmt in der Spezifikation, sonst hätte man das Problem unnötiger weiße bei anderen Versuchen Libs einzubinden ja auch.

    Soweit ich weis hat C++ keine einheitliche ABI, Microsoft hat allerdings durch COM einen quasi - Standard etabliert (also nicht für die komplette ABI sondern nur für die v-Table).

    floorball



  • Unter was ordnet man dann __stdcall, __fastcall usw. ein?



  • calling conventions, stammt aus C



  • Nathan schrieb:

    Belli schrieb:

    Ja, aber er reicht ja keine Instanzen (Objekte) herum, sondern lediglich Zeiger auf solche. Und das sollte meiner Meinung nach auch zwischen Client einer DLL und DLL keine Probleme bereiten.

    Naja, wenn Compiler A den vtable einer Klasse vor das Objekt packt und Compiler B ans Ende und dann in B eine DLL aus A geladen wird und versucht eine virtuelle Funktion aufzurufen....

    Ist das denn wirklich so schwer zu verstehen?

    MichelRT schrieb:

    Ansonsten ist es keine gute Idee Instanzen von Klassen als Parameter oder Rückgabewerte von Funktionen zu verwenden.

    Belli schrieb:

    Ja, aber er reicht ja keine Instanzen (Objekte) herum, sondern lediglich Zeiger auf solche.

    Was ist daran auszusetzen?



  • Belli schrieb:

    Nathan schrieb:

    Belli schrieb:

    Ja, aber er reicht ja keine Instanzen (Objekte) herum, sondern lediglich Zeiger auf solche. Und das sollte meiner Meinung nach auch zwischen Client einer DLL und DLL keine Probleme bereiten.

    Naja, wenn Compiler A den vtable einer Klasse vor das Objekt packt und Compiler B ans Ende und dann in B eine DLL aus A geladen wird und versucht eine virtuelle Funktion aufzurufen....

    Ist das denn wirklich so schwer zu verstehen?

    Genau dasselbe Problem ist auch mit Pointern...



  • Der sieht tatsächlich genauso aus wie der von ihm.

    typedef StrategyInterface*(__stdcall *getClass)(void);
    


  • @Nathan:
    Von verschiedenen Compilern war aber doch erst später die Rede. Zum Zeitpunkt meines Einwurfs hatte MichelRT darauf hingewiesen, dass man keine Objektinstanzen herumreichen soll und ich habe bemerkt, dass der TE das ja auch gar nicht tut.

    Dass für die DLL und die Anwendung derselbe Compiler verwendet wird, hat der TE auch schon (längst) erklärt:

    MichelRT schrieb:

    DLL und Dein Programm sind mit demselben Compiler und denselben Einstellungen erstellt?

    cl90 schrieb:

    Ja. Beide MSVC2012 beide x64 eingestellt.



  • Belli schrieb:

    @Nathan:
    Von verschiedenen Compilern war aber doch erst später die Rede. Zum Zeitpunkt meines Einwurfs hatte MichelRT darauf hingewiesen, dass man keine Objektinstanzen herumreichen soll und ich habe bemerkt, dass der TE das ja auch gar nicht tut.

    Ja, aber ich wollte lediglich klar stellen, dass das komplett egal ist, ob es Zeiger oder Instanzen sind.



  • Wie findet denn der Compiler die Adressen der Funktionen aus der DLL nur anhand des Headers?



  • Okay.... Was genau hast du gemacht "asdffdaöshge" ?

    bei mir funktioniert dein EXAKTER code nicht. er wirft die gleichen Fehler wie vorher.

    Das hier ist der Vollständige ungekürzte Code:

    DLL erstellen:

    #include <string>
    #include <Windows.h>
    
    using namespace std;
    
    	// DLL
    class StrategyInterface {
    public:
        virtual             ~StrategyInterface(){}
        virtual string      getStrategyName() = 0;
        virtual string      getStrategyBrief() = 0;
    };
    class Strategy : public StrategyInterface {
    public:
        string      getStrategyName() {
            return "blubb";
        }
        string      getStrategyBrief() {
            return "bla";
        }
    
    };
    #define STRATEGYDLL_API __declspec(dllexport)
    BOOL APIENTRY DllMain(HMODULE hModule,
                          DWORD dwReasonForCall,
                          LPVOID pReserved)
    {
        switch(dwReasonForCall)
        {
            case DLL_PROCESS_ATTACH:
                break;
            case DLL_PROCESS_DETACH:
                break;
        }
        return TRUE;
    }
    extern "C"
    STRATEGYDLL_API Strategy*   getClass() {
        return new Strategy;
    }
    

    Dll Lesen

    #include <string>
    #include <iostream>
    #include <Windows.h>
    
    using namespace std;
    
    // exe
    class StrategyInterface {
    public:
        virtual             ~StrategyInterface(){}
        virtual string      getStrategyName() = 0;
        virtual string      getStrategyBrief() = 0;
    };
    typedef StrategyInterface*(__stdcall *getClass)(void);
    int main()
    {
        HMODULE                 hDLL;
        getClass                fGet;
        StrategyInterface       *cClass;
    
        hDLL = LoadLibraryA("D:\\testDll.dll"); // Funktioniert, hDLL ist nicht null.
    
        if(hDLL == NULL)
        {
            MessageBoxA(NULL, "Can't load library!", "Error", NULL);
        }
        fGet = (getClass)(GetProcAddress(hDLL,"getClass"));  // Funktion wird auch gefunden.
        if(fGet == NULL)
        {
            MessageBoxA(NULL, "Can't get process address!", "Error", NULL);
        }
        else
        {
            StrategyInterface* bla = fGet();
            std::cout << bla->getStrategyName() << std::endl;     // hier gibt es einen Fehler.
        }
        system("pause");
    }
    

    edit:
    Getestet mit 32Bit compiler und mit x64. Beide mal wirft er die Exception beim Aufrufen der string Funktion.
    vlt wirds langsam relevant was für ein System ich hab...

    Win7 x64, mit MSVC 2010

    edit2:
    ... in Zwei völlig neuen Projekten funktioniert der Sourcecode.
    Ich beginne die Einstellungsfehlersuche 😞



  • Problem vorraussichtlich gefunden.
    Ich war mir sicher das ich es getestet hatte, aber irgendwie ist mir bei dem Test wohl ein Fehler unterlaufen.

    Starte ich Kompiler der dll und Kompiler der exe im debug modus läuft alles glatt. Eine Exceptions etc.
    Dll im release und exe im debug führt zu exceptions.

    Also entweder wirft die Dll jetzt immer noch exceptions welche durch den Release Modus nicht mehr gefangen/angezeigt werden, oder die dlls müssen im selben Mode kompiliert werden.
    Ich hoffe zweiteres, denn beide unter Debug, scheint ja super zu funktionieren.
    Seltsam aber gar nicht so abwegig...

    Ich Setze den Thread mal auf solved, aber fals jemand lust hat mir das zu erklären wäre ich da sehr dankbar.

    Danke nochmal 🙂

    Gruß,
    Chris


Anmelden zum Antworten