我遇到了这个问题,我希望能在这里找到一些帮助。我创建了一个展示问题的小示例可执行文件和共享库。共享库和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我已经更新了答案。 –