GNU/Linux >> Znalost Linux >  >> Linux

Statické propojení libstdc++:nějaké problémy?

Možná se také budete muset ujistit, že nejste závislí na dynamickém glibc. Spusťte ldd na výsledném spustitelném souboru a poznamenejte si všechny dynamické závislosti (libc/libm/libpthread jsou obvyklé podezřelé).

Dalším cvičením by bylo vytvoření řady zapojených příkladů C++ 11 pomocí této metodologie a skutečné vyzkoušení výsledných binárních souborů na skutečném systému 10.04. Ve většině případů, pokud s dynamickým načítáním neuděláte něco divného, ​​budete okamžitě vědět, zda program funguje nebo spadne.


Ten blogový příspěvek je dost nepřesný.

Pokud je mi známo, změny C++ ABI byly zavedeny s každým hlavním vydáním GCC (tj. těmi s různými komponentami první nebo druhé verze).

Není pravda. Jediné změny C++ ABI zavedené od GCC 3.4 byly zpětně kompatibilní, což znamená, že C++ ABI je stabilní téměř devět let.

Aby toho nebylo málo, většina hlavních linuxových distribucí používá snímky GCC a/nebo opravuje své verze GCC, takže je prakticky nemožné přesně vědět, s jakými verzemi GCC máte při distribuci binárních souborů co do činění.

Rozdíly mezi opravenými verzemi GCC distribucí jsou malé a nemění se ABI, např. Fedora 4.6.3 20120306 (Red Hat 4.6.3-2) je kompatibilní s ABI s upstream vydáními FSF 4.6.x a téměř jistě s jakýmkoli 4.6.x z jakékoli jiné distribuce.

V běhových knihovnách GNU/Linuxu GCC používají verzování symbolů ELF, takže je snadné zkontrolovat verze symbolů, které objekty a knihovny potřebují, a pokud máte libstdc++.so která poskytuje tyto symboly, bude to fungovat, nezáleží na tom, jestli se jedná o mírně odlišnou opravenou verzi od jiné verze vašeho distra.

ale žádný kód C++ (nebo jakýkoli kód využívající podporu běhového prostředí C++) nesmí být dynamicky propojen, pokud to má fungovat.

Ani to není pravda.

To znamená statické propojení s libstdc++.a je pro vás jedna možnost.

Důvod, proč nemusí fungovat, pokud dynamicky načítáte knihovnu (pomocí dlopen ) je, že symboly libstdc++, na kterých závisí, nemusela vaše aplikace potřebovat, když jste ji (staticky) propojili, takže tyto symboly nebudou ve vašem spustitelném souboru přítomny. To lze vyřešit dynamickým propojením sdílené knihovny s libstdc++.so (což je každopádně správná věc, pokud na tom závisí.) Vložení symbolů ELF znamená, že symboly, které jsou přítomné ve vašem spustitelném souboru, budou použity sdílenou knihovnou, ale ostatní, které nejsou přítomné ve vašem spustitelném souboru, budou nalezeny v kterémkoli libstdc++.so odkazuje na. Pokud vaše aplikace nepoužívá dlopen o to se nemusíte starat.

Další možností (a kterou preferuji) je nasazení novějšího libstdc++.so vedle vaší aplikace a ujistěte se, že je nalezena před výchozím systémem libstdc++.so , což lze provést vynucením dynamického linkeru, aby se podíval na správné místo, buď pomocí $LD_LIBRARY_PATH proměnnou prostředí za běhu nebo nastavením RPATH ve spustitelném souboru na link-time. Dávám přednost použití RPATH protože nespoléhá na správné nastavení prostředí, aby aplikace fungovala. Pokud svou aplikaci propojíte s '-Wl,-rpath,$ORIGIN' (všimněte si jednoduchých uvozovek, aby se shell nepokoušel rozšířit $ORIGIN ), pak bude mít spustitelný soubor RPATH z $ORIGIN který říká dynamickému linkeru, aby hledal sdílené knihovny ve stejném adresáři jako samotný spustitelný soubor. Pokud vložíte novější libstdc++.so ve stejném adresáři jako spustitelný soubor bude nalezen za běhu, problém vyřešen. (Další možností je umístit spustitelný soubor do /some/path/bin/ a novější libstdc++.so v /some/path/lib/ a propojit s '-Wl,-rpath,$ORIGIN/../lib' nebo jakékoli jiné pevné umístění vzhledem ke spustitelnému souboru a nastavte RPATH relativně na $ORIGIN )


Jeden dodatek k vynikající odpovědi Jonathana Wakelyho, proč je dlopen() problematický:

Vzhledem k novému fondu zpracování výjimek v GCC 5 (viz PR 64535 a PR 65434), pokud dlootevřete a dlzavřete knihovnu, která je staticky propojena s libstdc++, pokaždé dojde k úniku paměti (objektu fondu). Takže pokud existuje nějaká šance, že někdy použijete dlopen, zdá se být opravdu špatný nápad staticky propojit libstdc++. Všimněte si, že toto je skutečný únik na rozdíl od neškodného úniku uvedeného v PR 65434.


Linux
  1. Nativefier – snadno přeměňte jakýkoli web na desktopovou aplikaci

  2. Statické linkování Linuxu je mrtvé?

  3. C/C++ s GCC:Statické přidávání zdrojových souborů do spustitelného souboru/knihovny

  1. iconv libovolné kódování do UTF-8

  2. Proč musí být složka spustitelná?

  3. Jak nastavit soubor jako NENÍ spustitelný?

  1. Nějaký způsob, jak se vyhnout tečkovému lomítku při spouštění spustitelných skriptů v bash?

  2. Proč jsou soubory .so spustitelné?

  3. Propojení ethernetových rozhraní