c ++ - Statisk forbinder libgcc på Windows DLL

Indlæg af Hanne Mølgaard Plasc

Problem



Jeg skriver en Windows DLL i C ++. Dette bibliotek har kun C-grænseflade og bruger kun standard Windows-biblioteker, som også har C-interface. Derfor forekommer det mig sikkert at forbinde alle C ++-biblioteker statisk til biblioteket, fordi jeg ikke er afhængig af C ++ ABI-versionen, når jeg kun bruger C-grænseflader.


Desværre når jeg samler mit bibliotek med -static-stdc++ -static-libgcc, ophører mit bibliotek med at håndtere undtagelser, og når en vis undtagelse smides, kalder DLL sin statisk linkede \_Unwind\_RaiseException funktion, der afbryder hele applikationen.


Jeg troede det kunne være en ødelagt libgtcc.a, så jeg forsøgte at opdatere min compiler. Men resultatet er det samme med både MinGW 4.8 og MinGW 6.3.


Kan nogen være i stand til at forklare mig, hvad der virkelig sker her?


Klasyc

Bedste reference


Håndterer du alle undtagelser inde i DLL'en? Hvis nogen undtagelse 'lækker' uden for en funktion med en C   opkaldskonvention, vil den krasle applikationen.


Jeg har ingen problemer med C ++-undtagelser under MinGW x86\_64-5.3.0-win32-seh-rt\_v4-rev0 og mingw32 4.8.1 dwarf2 med en statisk libstdc ++/libgcc.


DLL-kilde (dll.cpp):


#include <windows.h>
#include <exception>
#include <iostream>

extern "C" {
\_\_declspec(dllexport) int \_\_stdcall test() {
    try {
        new int[-1];
        return 123;
    } catch (const std::exception& ex) {
        std::cerr << "Exception:" << ex.what() << std::endl;
        return 456;
    }
}
}

BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD     fdwReason, LPVOID    lpvReserved)
{
    return TRUE;
}


Programkilde (app.c):


#include <stdio.h>

#ifdef \_\_cplusplus
extern "C"
#endif
\_\_declspec(dllimport) int \_\_stdcall test();

int main() {
  printf("result: \%d
", test());
  return 0;
}


Kompilere det:


g++ -O2 -static-libgcc -static-libstdc++ -shared -Wl,--out-implib=dtest.lib -s -o dtest.dll dll.cpp


g++ -O2 -static-libgcc -static-libstdc++ -L. -s -o app app.c -ldtest


Produktion:


Exception:std::bad\_alloc
result: 456





For at svare på din kommentar ' Hvorfor har jeg brug for compiler med SEH-support? Jeg troede SEH tillader mig at fange Windows-undtagelser ' - på Windows er SEH de facto-standarden for alle undtagelser , herunder C ++-undtagelser (når de er udarbejdet med Visual C ++). MinGW har forskellige implementeringer for C ++-undtagelser (SEH, SJLJ og DWARF), men SEH er den eneste mekanisme med nul overhead, så hvis den er tilgængelig, skal du virkelig foretrække det over SJLJ og DWARF.

Andre referencer 1


Tak RastyX for det enkle eksempel i hans svar. Efter nogle undersøgelser fandt jeg ud af, at applikationen går i stykker, når jeg kompilerer DLL-del med -static-libgcc og applikationsdel uden denne switch (begge dele kompileret med samme g ++).


Også takket være Ripi2 til TDM-GCC forslag. Jeg forsøgte både SJLJ og DWARF-2 undtagelsesbehandling og begge arbejder.


For at konkludere det ser det ud til, at MinGWs libgcc ikke kan lide, når det er instansieret mere end én gang pr. Proces. I mit tilfælde bruger jeg en sin kopi i DLL (linket statisk) og en dens kopi i ansøgningen, og det bryder sandsynligvis undtagelsen håndtering.


På den anden side fokuserer TDM-GCC på statisk sammenkobling af basisbibliotekerne, som dens webside siger og producerer derfor binære filer, der kun afhænger af Windows-biblioteker selv uden -static-stdc++ -static-libgcc kommandolinjebryttere (det er det jeg vil have). Også undtagelseshåndteringen virker her, så ændring af værktøjskæden er den rigtige måde for mig.