gpt4 book ai didi

c++ - 使用共享库的段错误

转载 作者:太空宇宙 更新时间:2023-11-03 10:37:10 25 4
gpt4 key购买 nike

我有一个共享库(即 libXXX.so)和一个关联的 cpp/h 文件。它们包含许多函数指针(指向 .so 函数入口点)和一个将此函数包装为所述类的方法的类。

即:.h 文件:

typedef void* handle;
/* wrapper functions */
handle okUsbFrontPanel_Construct();
void okUsbFrontPanel_Destruct(handle hnd);

/* wrapper class */
class okCUsbFrontPanel
{
public:
handle h;
public:
okCUsbFrontPanel();
~okCUsbFrontPanel();
};

.cpp文件

/* class methods */
okCUsbFrontPanel::okCUsbFrontPanel()
{ h=okUsbFrontPanel_Construct(); }
okCUsbFrontPanel::~okCUsbFrontPanel()
{ okUsbFrontPanel_Destruct(h); }
/* function pointers */
typedef handle (*OKUSBFRONTPANEL_CONSTRUCT_FN) (void);
typedef void (*OKUSBFRONTPANEL_DESTRUCT_FN) (handle);
OKUSBFRONTPANEL_CONSTRUCT_FN _okUsbFrontPanel_Construct = NULL;
OKUSBFRONTPANEL_DESTRUCT_FN _okUsbFrontPanel_Destruct = NULL;
/* load lib function */
Bool LoadLib(char *libname){
void *hLib = dlopen(libname, RTLD_NOW);
if(hLib){
_okUsbFrontPanel_Construct = ( OKUSBFRONTPANEL_CONSTRUCT_FN ) dlsym(hLib, "okUsbFrontPanel_Construct");
_okUsbFrontPanel_Destruct = ( OKUSBFRONTPANEL_DESTRUCT_FN ) dlsym( hLib, "okUsbFrontPanel_Destruct" );
}
}
/* construct function */
handle okUsbFrontPanel_Construct(){
if (_okUsbFrontPanel_Construct){
handle h = (*_okUsbFrontPanel_Construct)(); //calls function pointer
return h;
}
return(NULL);
}

void okUsbFrontPanel_Destruct(handle hnd)
{
if (_okUsbFrontPanel_Destruct)
(*_okUsbFrontPanel_Destruct)(hnd);
}

然后我有另一个共享库(由我自己制作)调用:

LoadLib("libXXX.so");
okCusbFrontPanel *device = new okCusbFrontPanel();

导致段错误。段错误似乎发生在

handle h = (*_okUsbFrontPanel_Construct)();

但有一个奇怪的行为:一旦我到达

(*_okUsbFrontPanel_Construct)(); 

我递归到 okUsbFrontPanel_Construct()。

有人知道吗?

编辑:这是通过 gdb 运行获得的回溯。

#0  0x007590b0 in _IO_new_do_write () from /lib/tls/libc.so.6
#1 0x00759bb8 in _IO_new_file_overflow () from /lib/tls/libc.so.6
#2 0x0075a83d in _IO_new_file_xsputn () from /lib/tls/libc.so.6
#3 0x00736db7 in vfprintf () from /lib/tls/libc.so.6
#4 0x0073ecd0 in printf () from /lib/tls/libc.so.6
#5 0x02cb68ca in okCUsbFrontPanel (this=0x9d0ae28) at okFrontPanelDLL.cpp:167
#6 0x03cac343 in okUsbFrontPanel_Construct () from /opt/atlas/tdaq/tdaq-02-00-00/installed/i686-slc4-gcc34-dbg/lib/libokFrontPanel.so
#7 0x02cb8f36 in okUsbFrontPanel_Construct () at okFrontPanelDLL.cpp:1107
#8 0x02cb68db in okCUsbFrontPanel (this=0x9d0ade8) at okFrontPanelDLL.cpp:169
#9 0x03cac343 in okUsbFrontPanel_Construct () from /opt/atlas/tdaq/tdaq-02-00-00/installed/i686-slc4-gcc34-dbg/lib/libokFrontPanel.so
#10 0x02cb8f36 in okUsbFrontPanel_Construct () at okFrontPanelDLL.cpp:1107
#11 0x02cb68db in okCUsbFrontPanel (this=0x9d0ada8) at okFrontPanelDLL.cpp:169
#12 0x03cac343 in okUsbFrontPanel_Construct () from /opt/atlas/tdaq/tdaq-02-00-00/installed/i686-slc4-gcc34-dbg/lib/libokFrontPanel.so
#13 0x02cb8f36 in okUsbFrontPanel_Construct () at okFrontPanelDLL.cpp:1107

等等...恕我直言,由于某种堆栈溢出,我遇到了段错误。递归调用太多,出了点问题..

顺便说一句,我使用的是 Scientific Linux 4 发行版(基于 RH4)。

编辑2:

libokFrontPanel.so 的 objdump 函数 okUsbFrontPanel_Construct 输出:

00009316 <okUsbFrontPanel_Construct>:
9316: 55 push ebp
9317: 89 e5 mov ebp,esp
9319: 56 push esi
931a: 53 push ebx
931b: 83 ec 30 sub esp,0x30
931e: e8 44 f4 ff ff call 8767 <__i686.get_pc_thunk.bx>
9323: 81 c3 dd bd 00 00 add ebx,0xbddd
9329: c7 04 24 38 00 00 00 mov DWORD PTR [esp],0x38
9330: e8 93 ec ff ff call 7fc8 <_Znwj@plt>
9335: 89 45 e4 mov DWORD PTR [ebp-28],eax
9338: 8b 45 e4 mov eax,DWORD PTR [ebp-28]
933b: 89 04 24 mov DWORD PTR [esp],eax
933e: e8 65 ed ff ff call 80a8 <_ZN16okCUsbFrontPanelC1Ev@plt>
9343: 8b 45 e4 mov eax,DWORD PTR [ebp-28]
9346: 89 45 f4 mov DWORD PTR [ebp-12],eax
9349: 8b 45 f4 mov eax,DWORD PTR [ebp-12]
934c: 89 45 e0 mov DWORD PTR [ebp-32],eax
934f: eb 1f jmp 9370 <okUsbFrontPanel_Construct+0x5a>
9351: 89 45 dc mov DWORD PTR [ebp-36],eax
9354: 8b 75 dc mov esi,DWORD PTR [ebp-36]
9357: 8b 45 e4 mov eax,DWORD PTR [ebp-28]
935a: 89 04 24 mov DWORD PTR [esp],eax
935d: e8 d6 f2 ff ff call 8638 <_ZdlPv@plt>
9362: 89 75 dc mov DWORD PTR [ebp-36],esi
9365: 8b 45 dc mov eax,DWORD PTR [ebp-36]
9368: 89 04 24 mov DWORD PTR [esp],eax
936b: e8 a8 f0 ff ff call 8418 <_Unwind_Resume@plt>
9370: 8b 45 e0 mov eax,DWORD PTR [ebp-32]
9373: 83 c4 30 add esp,0x30
9376: 5b pop ebx
9377: 5e pop esi
9378: 5d pop ebp
9379: c3 ret

在 933e 确实调用了 <_ZN16okCUsbFrontPanelC1Ev@plt>。这个调用是否与我的 .cpp 中的调用混淆了?

最佳答案

现在您已经发布了 GDB输出,很清楚你的问题是什么。

您在 libokFrontPanel.so 中定义了相同的符号在libLoadLibrary.so (因为没有更好的名字 -- 当事物被正确命名时,所以更容易解释),导致了无限递归。

默认情况下,在 UNIX 上(与 Windows 不同)所有共享库(和主要可执行文件)中的所有全局符号都进入单个“加载程序符号 namespace ”。

除其他外,这意味着如果您定义 malloc在主可执行文件中,that malloc将被所有共享库调用,包括 libc (尽管 libc 有自己的 malloc 定义)。

所以,这是正在发生的事情:在 libLoadLibrary.so 中你定义了 okCUsbFrontPanel构造函数。我断言在 libokFrontPanel.so 中也有那个确切符号的定义。 . 所有 对此构造函数的调用(默认情况下)转到第一个定义(动态加载程序首先观察到的定义),即使 libokFrontPanel.so 的创建者也是如此。不打算发生这种情况。循环是(以相同的顺序 GDB 打印它们——最里面的框架在顶部):

 #1 okCUsbFrontPanel () at okFrontPanelDLL.cpp:169
#3 okUsbFrontPanel_Construct () from libokFrontPanel.so
#2 okUsbFrontPanel_Construct () at okFrontPanelDLL.cpp:1107
#1 okCUsbFrontPanel () at okFrontPanelDLL.cpp:169

#3 调用构造函数打算去符号 #4 -- okCUsbFrontPanel构造函数内部 libokFrontPanel.so .相反,它转到了之前在 libLoadLibrary.so 中看到的定义: 你“抢占”了符号#4,从而形成了一个无限递归循环。

道德:不要在多个库中定义相同的符号,除非您了解运行时加载程序决定哪些符号引用绑定(bind)到哪些定义的规则。

编辑:回答问题的“EDIT2”:
是的,调用_ZN16okCUsbFrontPanelC1Ev来自 okUsbFrontPanel_Construct将转到您的 okFrontPanelDLL.cpp 中该方法的定义.检查 objdump -d okFrontPanelDLL.o 可能很有启发性

关于c++ - 使用共享库的段错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1178538/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com