c++ - librt和对`mq_unlink'和 friend 的 undefined reference

标签 c++ linux ubuntu-16.04

我有一个用C++编写的系统,它构建了一组共享库和可执行文件,这些库和可执行文件链接到这些共享库(和系统库)。没有一个代码使用C++ 11,仅仅是OLE’C+++——在一个老的SUSELINUX 3.0.13,32位机器上,GCC 4.3.4的整个混乱。它附带了构建所有内容的makefile。我正在把整个系统转移到Ubuntu16.04上,它是一个64位处理器,带有GCC4.8。我有一些编译器的问题要解决,但我有一个很大的时间让东西链接。
所有共享库都会生成,但当我尝试生成可执行文件时,会出现很多“未定义引用”错误。我已经验证了来自这些错误的方法和Type信息确实存在于链接命令(-L)中的库中,并且这些库的路径也包含在链接命令(-L)中。我甚至创建了链接器映射,并验证了在共享库中确实存在显示为“unDebug”的类和方法。
通过在link命令中重新排列共享库列表,我设法解决了一些“未定义的引用”问题,但我不知道为什么这会有什么不同,因为相同的makefile在SUSE Linux上运行良好,不必担心库顺序然而,我仍然坚持几个项目。下面是一个例子:
我有一个可执行文件,它使用一个共享库(称为MQWrapper)为Linux消息队列提供一个包装器。该项目有一个使用以下命令编译的.cpp文件:

g++ -DZTRACE -DZDEV -I"." -I"../AppIncludes"  -I"../ZediCommon" \
    -I"../NetworkManagerCommon" -I"../TelitModemDriver" -I"../MQWrapper" \
    -I"../Hardware" -I"../WatchdogLib" -I"../BaseClasses" -O0 -g3 -Wall \
    -c -fmessage-length=0 -fPIC -MMD -MP -MF"Debug/NetworkProcess.d" \
    -o "Debug/NetworkProcess.o" "NetworkProcess.cpp"

它依赖于我系统中的其他共享库。它们的位置在link命令中由相对路径指定:
g++ -o Debug/networkmanager.1.2.0-DEV  ./Debug/NetworkProcess.o \
   -L../sharedlibs/Debug -lZediCommon -lMQWrapper -lBaseClasses \
   -lorm -lHardware -lWatchdogLib -llog4cplus-1.1 -lNetworkManagerCommon \
   -lpthread -lTelitModemDriver -ldl -lrt 

如您所见,“-lrt”在命令中。但是,当我尝试链接时,会出现以下链接器错误:
../sharedlibs/Debug/libMQWrapper.so: undefined reference to `mq_unlink'
../sharedlibs/Debug/libMQWrapper.so: undefined reference to `mq_close'
../sharedlibs/Debug/libMQWrapper.so: undefined reference to `mq_getattr'
../sharedlibs/Debug/libMQWrapper.so: undefined reference to `mq_receive'
../sharedlibs/Debug/libMQWrapper.so: undefined reference to `mq_open'
../sharedlibs/Debug/libMQWrapper.so: undefined reference to `mq_setattr'
../sharedlibs/Debug/libMQWrapper.so: undefined reference to `mq_send'

我已经验证了.Loop.So共享库的存在,并在链接器的搜索路径中。我甚至建立了一个小的测试程序,使用这些函数,编译和链接它,它建立得很好。
正如我所说,这只是一些“未定义引用”错误的示例,但我想我会使用这些错误,因为它们是系统的,而且可能最容易解决。
有人知道为什么会这样吗?有人能推荐一些调试技巧吗?SUSE的链接器和Ubuntu的链接器之间是否存在导致这些问题的差异?
更新
参考文章确实很好地解释了编译和链接的过程,并说明了可能的原因,这些都不适用于我的问题。我把所有的建议都写了。
我正在链接正确的库。具体来说,Linux消息队列函数是用librt.so实现的(或者至少应该是这样),链接器命令中有-lrt。
这些是Linux系统提供的函数,因此“声明但未定义变量或函数”不适用。没有编译器错误,因此函数原型从SUSE Linux匹配到Ubuntu Linux。
我正在调用提供C函数原型的Linux系统函数。”“纯虚拟”不适用
“虚拟方法必须实现或定义为纯”不适用。见3。
“非虚拟类成员”不适用。见3。
“一个常见的错误是忘记限定名称”不适用。见3。
“静态数据成员必须在类之外的单个转换单元中定义”不适用。见3。
“模板实现不可见”不适用。见3。
符号在C程序中定义,并在C++代码中使用。不适用。mqueue.h确实有“extern”C“包装函数原型。
不适用于跨模块/dll(特定于编译器)错误地导入/导出方法/类。我在Linux上工作
“如果其他的都失败了,重新编译。”已经做了…很多次了。
“成为模板的好友…”。见3。
“UNICODE定义不一致”。不适用。
“当包含路径不同时”。见2。
“链接在引用库的对象文件之前使用库”。不是这样。命令行显示加载的顺序。我也试过改变顺序。
在const变量声明/定义(仅C++)中“缺失”外部。见2。
“图书馆的不同版本”。我不会链接任何未在所述系统上构建的文件。因为我正在编译和链接系统库,所以这不是问题所在。
“链接到共享库时,请确保未隐藏使用的符号”。我没有在任何地方使用“-fvisibility=hidden”。
唯一有用的帖子是劳伦斯建议的。使用-v-Wl,-verbose。它验证了链接器正在查找librt.so并加载它。现在,如果有人建议为什么链接器找不到mq符号。

最佳答案

“链接在引用库的对象文件之前使用库”。不是这样。命令行显示加载的顺序。我也试过改变顺序。
这可能还是你的问题。由于依赖于系统库的是库,而不是对象文件,所以您的情况很复杂。
您可能需要在链接器命令行中的多个位置提到-lrt

关于c++ - librt和对`mq_unlink'和 friend 的 undefined reference ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53660044/

相关文章:

C getopt 不读取所有参数

c++ - 编译 STL map 插入时出现问题

linux - Bash 提示出现在输出中间

r - fread 系统区域设置错误

C++ 在初始化列表中的基类初始化之前调用函数

linux - 匹配模式后打印段落

c++ - 用数组或 vector 实现多维数组

linux - 无法在 .gitconfig 文件中添加(任何)全局 git 配置

c++ - 按大小 union 中不相交集 union 路径压缩的后果

c++ - 如何在 C++ Builder 中隐藏 PageControl TabSheets 的标题