【发布时间】:2020-12-17 20:29:14
【问题描述】:
在this answer 到关于compiling additional code at runtime in C or C++ 的问题之后,我准备了这个主程序
#include <dlfcn.h>
#include <stdlib.h>
#include <iostream>
using namespace std;
int main()
{
// create library
system ( "/usr/bin/gcc -fPIC -shared test.cpp -o libtest.so" );
// load library
void* fLib = dlopen ( "./libtest.so", RTLD_LAZY );
if ( !fLib ) {
cerr << "Cannot open library: " << dlerror() << '\n';
}
if ( fLib ) {
void ( *fn ) () = reinterpret_cast<void (*)()>(dlsym(fLib, "test"));
if ( fn ) {
fn();
}
dlclose ( fLib );
}
return 0;
}
那应该是把“test.cpp”编译成当前目录下的动态库libtest.so,加载库,在库中找到test函数并调用这个函数,但貌似dlsym找不到该功能,即使它在那里。
这是test.cpp 文件:
#include <iostream>
void test()
{
std::cout << "TEST" << std::endl;
}
main.cpp 编译时使用
g++ -ldl main.cpp -o main
当我执行它时,什么也没有发生:库已加载但fn 指针不可用,这意味着在libtest.so 中找不到该函数。
如果我用nm -gD 查看libtest.so 中的符号,我会看到测试函数:
nm -gD libtest.so
U __cxa_atexit@@GLIBC_2.2.5
w __cxa_finalize@@GLIBC_2.2.5
w __gmon_start__
w _ITM_deregisterTMCloneTable
w _ITM_registerTMCloneTable
0000000000001139 T _Z4testv
U _ZNSolsEPFRSoS_E
U _ZNSt8ios_base4InitC1Ev
U _ZNSt8ios_base4InitD1Ev
U _ZSt4cout
U _ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_
U _ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc
和
c++filt _Z4testv
test()
为什么dlsym 找不到test()?如何让它找到测试功能?
【问题讨论】:
-
我知道重命名是什么(使用 c++filt 对问题中的名称进行了分解),我该如何解决这个问题?有什么具体的东西可以让
dlsym知道这个名字被破坏了吗? -
我应该对损坏的名称进行硬编码吗?这听起来不像是一个稳定的解决方案:)
-
谢谢!稳定:如果函数名的修改方式从一个 gcc 版本更改为下一个版本怎么办?