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

时间:2022-10-22 22:43:51

The problem I am having is a little hard to explain, but I will try to put it in a simple way (I have no more ideas on how to solve it).

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

Well, basically, we have a very big C++ project on linux. This project was compiled with makefiles, but in the new version we are migrating it to CMake. The CMake version is compiling fine, but the behavior when loading a library is a little different.

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

Here is the scenario: I have a folder with the following files:

下面是场景:我有一个文件夹,文件夹中有以下文件:

/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)

There is a class called "tTOPClient", which is compiled inside the executable and inside the library. The idea is: if the library exists, the program should execute the functions inside the library. Otherwise, it should execute its own function.

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

Here is the stack when executing the appserver_original:

执行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

In summary, the sequence of calls:

综上所述,通话顺序如下:

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)

When I run the "appserver_cmake", the "APTC_Connect" is calling the library's "v40TC_m4GLConnect", but this function is called the "tTOPClient::m4GLConnect" that is inside the executable, and not the one inside itself.

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

Here is the stack:

这是堆栈:

    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

In summary:

总而言之:

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!!!)

Do someone know what could be causing this different behavior? The makefiles and the CMakeLists are too big to post here, but I've compared them and they seem to be similar. I've tried to make a small example, but I couldn't reproduce the problem.

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

2 个解决方案

#1


1  

I would also suspect different flags being passed to compiler or linker. I would compile everything, then touch only one cpp file and compile the cmake build like this:

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

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

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

The VERBOSE=1 leads to make showing the parameters which are passed to gcc. Then compile with your old makefile

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

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

让- f Makefile。老> log-oldmakefile.txt

When you find flags which are different between the two compiler / linker invocations look at these cmake variables:

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

  • CMAKE_CXX_FLAGS
  • CMAKE_CXX_FLAGS
  • CMAKE_CXX_FLAGS_RELEASE
  • CMAKE_CXX_FLAGS_RELEASE
  • CMAKE_SHARED_LINKER_FLAGS
  • CMAKE_SHARED_LINKER_FLAGS

information about the meaning of the variables is in the cmake wiki

有关变量含义的信息在cmake wiki中。

#2


2  

Both cmake and make have no direct effect on the generated executables, but only call the compiler. A compiler result is fully specified by its input parameters, so if cmake and make output the same compiler invocations, the resulting executable should show the same behaviour.

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

In short: Compare the output of make and cmake (you'll probably have to give cmake some flags so it shows the real invocations instead of its default useless progress indicators), and see (grep, sort, diff) where the compiler invocations differ.

简而言之:比较make和cmake的输出(您可能需要给cmake一些标志,以便它显示真正的调用,而不是它默认的无用的进度指示器),并查看(grep, sort, diff)编译器调用的不同之处。

#1


1  

I would also suspect different flags being passed to compiler or linker. I would compile everything, then touch only one cpp file and compile the cmake build like this:

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

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

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

The VERBOSE=1 leads to make showing the parameters which are passed to gcc. Then compile with your old makefile

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

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

让- f Makefile。老> log-oldmakefile.txt

When you find flags which are different between the two compiler / linker invocations look at these cmake variables:

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

  • CMAKE_CXX_FLAGS
  • CMAKE_CXX_FLAGS
  • CMAKE_CXX_FLAGS_RELEASE
  • CMAKE_CXX_FLAGS_RELEASE
  • CMAKE_SHARED_LINKER_FLAGS
  • CMAKE_SHARED_LINKER_FLAGS

information about the meaning of the variables is in the cmake wiki

有关变量含义的信息在cmake wiki中。

#2


2  

Both cmake and make have no direct effect on the generated executables, but only call the compiler. A compiler result is fully specified by its input parameters, so if cmake and make output the same compiler invocations, the resulting executable should show the same behaviour.

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

In short: Compare the output of make and cmake (you'll probably have to give cmake some flags so it shows the real invocations instead of its default useless progress indicators), and see (grep, sort, diff) where the compiler invocations differ.

简而言之:比较make和cmake的输出(您可能需要给cmake一些标志,以便它显示真正的调用,而不是它默认的无用的进度指示器),并查看(grep, sort, diff)编译器调用的不同之处。