库在可执行文件内调用函数,而不是在库内

Posted

技术标签:

【中文标题】库在可执行文件内调用函数,而不是在库内【英文标题】:A library is calling a function inside the executable, and not inside the library 【发布时间】:2011-12-30 12:24:03 【问题描述】:

我遇到的问题有点难以解释,但我会尽量用简单的方式来说明(我对如何解决它没有更多的想法)。

嗯,基本上,我们在 linux 上有一个非常大的 C++ 项目。这个项目是用 makefile 编译的,但在新版本中我们将它迁移到 CMake。 CMake 版本编译良好,但加载库时的行为略有不同。

这是场景:我有一个包含以下文件的文件夹:

/appserver/appserver_cmake (the binary compiled using cmake)
/appserver/appserver_original (the binary compiled using the makefiles)
/appserver/dbsrv.so (the library the program is trying to load)

有一个名为“tTOPClient”的类,它在可执行文件和库中编译。这个想法是:如果库存在,程序应该执行库中的函数。否则,它应该执行自己的功能。

这是执行appserver_original时的堆栈:

    bAdvplConn=0 '\000') at ../fatclient/clientconn.cpp:260
#1  0xb6396fe2 in tTOPClient::m4GLConnect (this=0x2075d858, server=0x2075e3d4 "(local)", environment=0x2075e404 "ORACLE", 
    user=0x203c6731 "user") at ../fatclient/clientconn.cpp:255
#2  0xb63a0f1d in v40TC_m4GLConnect (who=0x2075d858, toServer=0x2075e3d4 "(local)", init_prm=0x2075e404 "@!!@ORACLE/ora10g_v1002t", usr=0x203c6731 "user")
    at ../fatclient/topapi40.cpp:63
#3  0x0866e49c in tTopDriver::APTC_Connect (this=0x2075e4d0, who=0x2075d858, toServer=0x2075e3d4 "(local)", conn_str=0x2075e404 "ORACLE", 
    usrname=0x203c6731 "user", nSeed=-1230926992) at ./lib/top.cpp:3718
#4  0x0866d0eb in tTopDriver::Connect (this=0x2075e4d0) at ./lib/top.cpp:3314

总之,调用顺序:

tTopDriver::Connect (inside the executable)
tTopDriver::APTC_Connect (inside the executable, will call a library's function)
v40TC_m4GLConnect (inside the library)
tTOPClient::m4GLConnect (inside the library)

当我运行“appserver_cmake”时,“APTC_Connect”正在调用库的“v40TC_m4GLConnect”,但这个函数被称为可执行文件内部的“tTOPClient::m4GLConnect”,而不是它本身。

这是堆栈:

    bAdvplConn=0 '\000') at /home/user/adv/trunk/topconnect/4.0/client/clientconn.cpp:207
#1  0x08abe8d2 in tTOPClient::m4GLConnect (this=0x20a1d528, server=0x20a1d78c "(local)", environment=0x20a1ffcc "ORACLE", 
    user=0x20600c69 "user") at /home/user/adv/trunk/topconnect/4.0/client/clientconn.cpp:202
#2  0xae1a0f1d in v40TC_m4GLConnect (who=0x20a1d528, toServer=0x20a1d78c "(local)", init_prm=0x20a1ffcc "ORACLE", usr=0x20600c69 "user")
    at ../fatclient/topapi40.cpp:63
#3  0x08982730 in tTopDriver::APTC_Connect (this=0x209f0780, who=0x20a1d528, toServer=0x20a1d78c "(local)", conn_str=0x20a1ffcc "ORACLE", 
    usrname=0x20600c69 "user", nSeed=-1335784592) at /home/user/adv/trunk/lib/top.cpp:3718
#4  0x0898137f in tTopDriver::Connect (this=0x209f0780) at /home/user/adv/trunk/lib/top.cpp:3314

总结:

tTopDriver::Connect (inside the executable)
tTopDriver::APTC_Connect (inside the executable, will call a library's function)
v40TC_m4GLConnect (inside the library)
tTOPClient::m4GLConnect (inside the executable!!!)

有人知道是什么导致了这种不同的行为吗? makefile 和 CMakeList 太大,无法在此处发布,但我已经比较了它们,它们似乎很相似。我试着做一个小例子,但我无法重现这个问题。

【问题讨论】:

【参考方案1】:

cmakemake 都对生成的可执行文件没有直接影响,只是调用编译器。编译器结果完全由其输入参数指定,因此如果 cmakemake 输出相同的编译器调用,则生成的可执行文件应显示相同的行为。

简而言之:比较makecmake 的输出(您可能必须给cmake 一些标志,以便它显示真正的调用而不是默认的无用进度指示器),然后查看(@987654328 @, sort, diff) 编译器调用不同的地方。

【讨论】:

过去 2 天我已经尝试过,但我找不到相关的东西。输出非常大(项目编译大约需要 1 小时),差异显示一切不同,因为 CMake 改变了编译的顺序(这会导致行为不同吗?) @RenanGreinert:理论上可以,但这种情况很少见,因为每个编译步骤都有一个明确定义的输出,在编译前不可用,编译后完全可用。尝试sorting 你的编译器调用是顺序无关的。顺便说一句,1 小时不是一个大项目,甚至我的一个人博士项目也需要半小时:-)。【参考方案2】:

我也怀疑不同的标志被传递给编译器或链接器。我会编译所有内容,然后只触摸一个 cpp 文件并像这样编译 cmake 构建:

VERBOSE=1 make -j1 > log-cmake.txt

VERBOSE=1 导致显示传递给 gcc 的参数。然后用旧的 makefile 编译

make -f Makefile.old > log-oldmakefile.txt

当您发现两个编译器/链接器调用之间的标志不同时,请查看这些 cmake 变量:

CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS_RELEASE CMAKE_SHARED_LINKER_FLAGS

关于变量含义的信息在the cmake wiki

【讨论】:

以上是关于库在可执行文件内调用函数,而不是在库内的主要内容,如果未能解决你的问题,请参考以下文章

在可执行文件中使用嵌入式 .dll

strace 'open' 在可执行文件库中调用

在可执行的 .jar 文件中包含 excel

在可执行文件中使用 GNU 标准目录变量

在 Windows cmd 中,如何在当前目录中运行可执行文件(而不是在 %PATH% 中具有相同名称的可执行文件)而不参考完整路径? [关闭]

在可执行 jar 中访问 derby 数据库