我遇到了這個問題,我希望能在這裏找到一些幫助。我創建了一個展示問題的小示例可執行文件和共享庫。共享庫和libpthread.so的g ++問題
對不起,我意識到這已經變成了一面牆,但我試圖確保包括所有相關信息。
我的設置
System: CentOS release 5.11 (Final)
g++: gcc version 4.4.7 20120313 (Red Hat 4.4.7-1) (GCC)
libc.so.6: Compiled by GNU CC version 4.1.2 20080704 (Red Hat 4.1.2-55).
我也有類似的結果想這一個RedHat 6.6的機器上。
我的情景:
我有一個在嘗試通過加載共享庫的應用程序運行時通過:: dlopen的()。如果我沒有在pthread中鏈接,那麼它看起來可以工作,但最終會在試圖拋出異常的共享庫中崩潰。原因在於系統運行時庫的構建期望線程本地存儲(TLS),異常處理使用來自TLS的數據結構,但在這種情況下,它是NULL並導致崩潰。這些函數是__cxa_allocate_exception和__cxa_get_globals,看起來他們使用libc中的存根函數,因爲pthread未鏈接。
我現在遇到的問題是嘗試在pthread中鏈接以更正上述問題。如果我使用pthread構建,應用程序段錯誤嘗試加載libpthread.so.0作爲我的共享庫的依賴項。我讀過的關於這次崩潰的一切是,應用程序是在沒有pthread的情況下構建的,而共享庫是用pthread構建的。不過,我正在用pthread構建兩個二進制文件,但我仍然遇到此問題。
示例代碼:
共享庫文件(* FOO)
foo.h中
#pragma once
extern "C"
{
extern void DoWork();
}
Foo.cpp中
#include "foo.h"
#include <stdio.h>
void DoWork()
{
printf("SharedLibrary::DoWork()\n");
}
應用程序文件(主。 cpp)
的main.cpp
#include "foo.h"
#include <stdio.h>
#include <dlfcn.h>
void LoadSharedLibrary()
{
void* handle = 0;
void(*function)();
try
{
printf("Loading the shared library\n");
handle = ::dlopen("libfoo.so", 2);
function = (void (*)())::dlsym(handle, "DoWork");
printf("Done loading the shared library\n");
function();
}
catch(...)
{
printf("ERROR - Exception while trying to load the shared library\n");
}
}
int main(int argc, char* argv[])
{
LoadSharedLibrary();
return 0;
}
顯式加載
嘗試使用以下構建腳本導致段錯誤試圖加載libpthread.so.0加載在運行時的共享庫。
構建腳本:
compiler=g++
arch=-m32
echo gcc architecture flag: ${arch}
${compiler} -c -fPIC -g ${arch} -pthread -o ./foo.o foo.cpp
${compiler} ${arch} -shared -g -o ./libfoo.so ./foo.o -lpthread
${compiler} -c -fPIC -g ${arch} -pthread -o ./main.o main.cpp
${compiler} ${arch} -static -g -o main.out ./main.o -lpthread -ldl -lc
這個崩潰的堆棧跟蹤是:
#0 0x00000000 in ??()
#1 0x0089a70a in __pthread_initialize_minimal_internal() at init.c:417
#2 0x0089a218 in call_initialize_minimal() from /lib/libpthread.so.0
#3 0x00899da8 in _init() from /lib/libpthread.so.0
#4 0x0808909b in call_init()
#5 0x080891b0 in _dl_init()
#6 0x08063a87 in dl_open_worker()
#7 0x0806245a in _dl_catch_error()
#8 0x0806349e in _dl_open()
#9 0x08053106 in dlopen_doit()
#10 0x0806245a in _dl_catch_error()
#11 0x08053541 in _dlerror_run()
#12 0x08053075 in __dlopen()
#13 0x0804830f in dlopen()
#14 0x0804824f in LoadSharedLibrary() at main.cpp:13
#15 0x080482d3 in main (argc=1, argv=0xffffd3e4) at main.cpp:27
加載的共享庫:
From To Syms Read Shared Object Library
0xf7ffb3b0 0xf7ffb508 Yes libfoo.so
0x0089a210 0x008a5bc4 Yes (*) /lib/libpthread.so.0
0xf7f43670 0xf7fbec24 Yes (*) /usr/lib/libstdc++.so.6
0x009a8410 0x009c35a4 Yes (*) /lib/libm.so.6
0xf7efb660 0xf7f02f34 Yes (*) /lib/libgcc_s.so.1
0x0074dcc0 0x0084caa0 Yes (*) /lib/libc.so.6
0x007197f0 0x0072f12f Yes (*) /lib/ld-linux.so.2
(*): Shared library is missing debugging information.
隱正在加載
這使用了一個不同的構建腳本,它試圖在構建時設置依賴關係,理論上不需要顯式的加載調用。這不是我們真實世界場景的有效用例,但我在試圖解決這個問題時試圖做到這一點。
構建腳本:
compiler=g++
arch=-m32
echo gcc architecture flag: ${arch}
${compiler} -c -fPIC -g ${arch} -pthread -o ./foo.o foo.cpp
${compiler} ${arch} -shared -g -o ./libfoo.so ./foo.o -lpthread
${compiler} -c -fPIC -g ${arch} -pthread -o ./main.o main.cpp
${compiler} ${arch} -static -g -L. -o main.out ./main.o -lpthread -ldl -Wl,-Bdynamic -lfoo -Wl,-static -lc
行爲:
Starting program: /app_local/dev3/stack_overflow/main.out
/bin/bash: /app_local/dev3/stack_overflow/main.out: /usr/lib/libc.so.1: bad ELF interpreter: No such file or directory
/bin/bash: /app_local/dev3/stack_overflow/main.out: Success
在啓動程序退出,代碼爲1
奇怪的是,我已經做了objdump -p <library> | grep NEEDED
並沒有庫在依賴鏈中有libc.so.1
作爲依賴關係。他們依賴的libc版本是libc.so.6
。
的建設場景
我真的希望有人在這裏結束了關於正在發生的事情的想法,並可以幫助我。我的Google和StackOverflow技能使我失敗了,因爲我發現的一切都指出pthread使用不匹配是根本問題。
在此先感謝!
@EmployedRusian介意我選擇你的大腦?這當然是一個很大的遺留應用程序(20多歲),我們試圖一次更新碎片。在這種情況下,情況並非總是如此嗎? 靜態鏈接的應用程序構建過程很難修改,所以我一直在試圖用最小的mod來做什麼(嘗試去除下一個靜態鏈接)。我確實嘗試將應用程序更改爲鏈接libpthread.so,動態地將所有其他內容保留爲靜態。你認爲這應該工作,因爲它可以避免衝突的pthread庫? – Scott
當我得出幾乎相同的結論時,也將此標記爲答案,但沒有@EmployedRussian提供的基本原因。 謝謝! – Scott
@Scott我已經更新了答案。 –