C++ 库调用的是可执行文件中的函数,而不是库中的函数

C++ 库调用的是可执行文件中的函数,而不是库中的函数,c++,linux,cmake,C++,Linux,Cmake,我遇到的问题有点难以解释,但我会尽量用一种简单的方式来解释(我对如何解决它没有更多的想法) 基本上,我们在Linux上有一个非常大的C++项目。这个项目是用makefile编译的,但是在新版本中,我们将它迁移到CMake。 CMake版本编译良好,但加载库时的行为略有不同 以下是场景:我有一个包含以下文件的文件夹: /appserver/appserver_cmake (the binary compiled using cmake) /appserver/appserver_original

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

基本上,我们在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_原件时的堆栈:

    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\u cmake”时,“APTC\u Connect”正在调用库的“v40TC\u 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!!!)

有人知道是什么导致了这种不同的行为吗?makefiles和CmakeList太大了,无法在这里发布,但是我比较了它们,它们看起来很相似。我试着做一个小例子,但我无法重现这个问题。

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


简而言之:比较
make
cmake
的输出(您可能需要给
cmake
一些标志,以便它显示实际调用,而不是默认的无用进度指示器),然后查看(
grep
排序
diff
)编译器调用不同的地方。

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

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

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

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

当您找到两个编译器/链接器调用之间不同的标志时,请查看以下cmake变量:

  • CMAKE_CXX_标志
  • CMAKE\U CXX\U标志\U发布
  • CMAKE_共享链接器_标志

关于变量含义的信息在

中,在过去的两天里,我一直在尝试,但找不到相关的信息。输出非常大(项目编译大约需要1小时),差异显示了所有不同之处,因为CMake改变了编译顺序(这会导致行为上的差异吗?@RenanGreinert:理论上可能,但情况很少如此,因为每个编译步骤都有一个定义良好的输出,该输出在编译之前不可用,在编译之后完全可用。尝试
sort
将编译器调用设置为顺序独立。顺便说一句,1小时不是一个大项目,即使是我的一人博士项目也需要半小时:-)。