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_;即可消除链接错误。

相关推荐
_wyt0014 小时前
洛谷 B3930 [GESP202312 五级] 烹饪问题 题解
c++·gesp
玖玥拾7 小时前
C/C++ 数据结构(七)栈、容器适配器
c语言·数据结构·c++··容器适配器
один but you9 小时前
constexpr函数
c++
凡人叶枫9 小时前
Effective C++ 条款41:了解隐式接口和编译期多态
java·开发语言·c++·effective c++
凡人叶枫9 小时前
Effective C++ 条款42:了解 typename 的双重意义
java·linux·服务器·c++
小胖xiaopangss9 小时前
BRpc使用
c++·rpc
-森屿安年-10 小时前
63. 不同路径 II
c++·算法·动态规划
chase_my_dream10 小时前
Cartographer详细讲解
c++·人工智能·自动驾驶
森G10 小时前
75、服务器源码解析---------云视频服务项目
linux·服务器·网络·c++·qt
碧海蓝天202210 小时前
C++法则24:在标准 C++ 中,没有任何可移植的方式判断指针 T* pt 指向的内存位置是否已经 构造了对象,程序员必须手动跟踪哪些元素已构造。
java·开发语言·c++