C++纯虚基类和类的静态成员未定义引起的链接问题

C++中基类如果是纯虚类,并且析构函数做了声明但未定义的话,编译可以过,链接时会导致报错说该类未定义。类有static变量成员时,如果未定义,链接会报错这个变量未定义。这些语法细节不记得的话,遇到错误时只看表面的错误信息,一下想不起来为什么报错有点浪费时间,做下记录。

例如:

E0103 22:47:55.505376 42954 class_loader_utility.cc:218] mainboardLibraryLoadException: /apollo/bazel-bin/modules/perception/image_stitch/../../../_solib_local/_U_S_Smodules_Sperception_Simage_Ustitch_Cimagestitch_Udceplus___Umodules_Sperception_Simage_Ustitch_Sbuild_Ux86/libdcepluscuda.so: undefined symbol: _ZTIN6apollo10perception6camera11imagestitch3pre13NormalizationE library_path:/apollo/bazel-bin/modules/perception/image_stitch/libimage_stitch_component.so

E0103 22:47:55.505409 42954 class_loader_utility.cc:234] mainboardshared library failed: /apollo/bazel-bin/modules/perception/image_stitch/libimage_stitch_component.so

E0103 22:47:55.505439 42954 class_loader_manager.h:78] mainboardInvalid class name: ImageStitchComponent

E0103 22:47:55.505457 42954 module_controller.cc:69] mainboardFailed to load module: modules/perception/image_stitch/dag/image_stitch.dag

E0103 22:47:55.505462 42954 class_loader_utility.cc:256] mainboardAttempt to UnloadLibrary lib, but can't find lib: /apollo/bazel-bin/modules/perception/image_stitch/libimage_stitch_component.so

E0103 22:47:55.505466 42954 mainboard.cc:39] mainboardmodule start error.

执行命令

nm -D /apollo/bazel-bin/modules/perception/image_stitch/../../../_solib_local/_U_S_Smodules_Sperception_Simage_Ustitch_Cimagestitch_Udceplus___Umodules_Sperception_Simage_Ustitch_Sbuild_Ux86/libdceplusnorm.so |grep "_ZTIN6apollo10perception6camera11imagestitch3pre13NormalizationE"

得到结果

U _ZTIN6apollo10perception6camera11imagestitch3pre13NormalizationE

输出显示 U(Undefined),说明这个符号在 libdceplusnorm.so 中是被引用的,而不是被定义的。执行下面的命令查看typeinfo:

c++filt _ZTIN6apollo10perception6camera11imagestitch3pre13NormalizationE

输出 typeinfo for apollo::perception::camera::imagestitch::pre::Normalization

那可能的原因是:包含Normalization类定义的源文件没有被编译进任何库或类是纯虚类,但缺少至少一个虚函数的实现,或者链接时缺少包含该类实现的库。这里属于第一种情况,Normalization类是纯虚基类,要确保至少析构函数在 .cpp 文件中有实现定义,哪怕是空的:

normalization.hpp

class Normalization {

public:

virtual ~Normalization();

// ...

};

需要在normalization.cpp里增加下面这句才不会报链接错误,因为子类析构时需要调用到基类的析构函数,基类的析构函数需要有实现:

Normalization::~Normalization() = default;

或者把normalization.hpp里的virtual ~Normalization(); 删掉也不会报链接报错,但这个不规范,相当于让编译器去隐式实现,编译器的实现做得不好可能会在运行时出现莫名其妙的崩溃问题。

加了定义后再执行命令

nm -D /apollo/bazel-bin/modules/perception/image_stitch/../../../_solib_local/_U_S_Smodules_Sperception_Simage_Ustitch_Cimagestitch_Udceplus___Umodules_Sperception_Simage_Ustitch_Sbuild_Ux86/libdceplusnorm.so |grep "_ZTIN6apollo10perception6camera11imagestitch3pre13NormalizationE"

可以看到库文件里的符号有对应地址了:

00000000002a3fb8 V _ZTIN6apollo10perception6camera11imagestitch3pre13NormalizationE

E0124 18:43:53.675529 6208 class_loader_utility.cc:218] mainboardLibraryLoadException: /apollo/bazel-bin/modules/perception/multi_sensor_fusion/../../../_solib_local/_U_S_Smodules_Sperception_Smulti_Usensor_Ufusion_Cmulti_Usensor_Ufusion_Ulib___Umodules_Sperception_Smulti_Usensor_Ufusion/libmulti_sensor_fusion_lib.so: undefined symbol: _ZN6apollo10perception6fusion26MultiSensorFusionComponent16s_mutex_pkslots_E library_path:/apollo/bazel-bin/modules/perception/multi_sensor_fusion/libmulti_sensor_fusion.so

E0124 18:43:53.675557 6208 class_loader_utility.cc:234] mainboardshared library failed: /apollo/bazel-bin/modules/perception/multi_sensor_fusion/libmulti_sensor_fusion.so

用c++filt _ZN6apollo10perception6fusion26MultiSensorFusionComponent16s_mutex_pkslots_E

可以看到MultiSensorFusionComponent类的静态成员变量s_mutex_pkslots_未正确定义,在头文件中声明了:

static std::mutex s_mutex_pkslots_;

但在.cc文件中没有定义,增加std::mutex MultiSensorFusionComponent::s_mutex_pkslots_;即可消除链接错误。

相关推荐
问君能有几多愁~8 小时前
C++ 数据结构复习笔记
数据结构·c++·笔记
tntxia8 小时前
C++ 基础教程:从入门到精通
c++
Drone_xjw8 小时前
从 GDB 到 CDB:C/C++ 程序调试的两把“手术刀”
c语言·开发语言·c++
熊猫_豆豆12 小时前
QT6 Android C++ 自制美观闹钟
android·c++·qt·闹钟
随意起个昵称12 小时前
状压dp-基础题目2([USACO12MAR] Cows in a Skyscraper G)
c++·算法·动态规划
无限的鲜花13 小时前
协程本质是函数加状态机——零基础深入浅出 C++20 协程
c++·算法·c++20
精明的身影14 小时前
C++自学之路1:Hello world
开发语言·c++
旖-旎14 小时前
《LeetCode 64 最小路径和 || LeetCode 174 地下城游戏》
c++·算法·leetcode·动态规划
森林古猿114 小时前
再论斜率优化
c++·学习·算法
水利行业RTU手艺人14 小时前
RTU固件中的“数据保险箱”——离线数据补发系统设计
c++·stm32·单片机·物联网