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

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

例如:

E0103 22:47:55.505376 42954 class_loader_utility.cc:218] [mainboard]LibraryLoadException: /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] [mainboard]shared library failed: /apollo/bazel-bin/modules/perception/image_stitch/libimage_stitch_component.so

E0103 22:47:55.505439 42954 class_loader_manager.h:78] [mainboard]Invalid class name: ImageStitchComponent

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

E0103 22:47:55.505462 42954 class_loader_utility.cc:256] [mainboard]Attempt 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] [mainboard]module 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] [mainboard]LibraryLoadException: /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] [mainboard]shared 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_;即可消除链接错误。

相关推荐
xiaoye-duck1 小时前
《算法题讲解指南:递归,搜索与回溯算法--递归》--3.反转链表,4.两两交换链表中的节点,5.快速幂
数据结构·c++·算法·递归
山栀shanzhi1 小时前
归并排序(Merge Sort)原理与实现
数据结构·c++·算法·排序算法
Trouvaille ~1 小时前
【递归、搜索与回溯】专题(七):FloodFill 算法——勇往直前的洪水灌溉
c++·算法·leetcode·青少年编程·面试·蓝桥杯·递归搜索回溯
zhooyu2 小时前
二维坐标转三维坐标的实现原理
c++·3d·opengl
10Eugene3 小时前
C++/Qt自制八股文
java·开发语言·c++
「QT(C++)开发工程师」3 小时前
C++11 新特性 正则表达式、随机数库、元组
c++·正则表达式
free-elcmacom4 小时前
C++ 默认参数详解:用法、规则与避坑指南
开发语言·c++
Albert Edison4 小时前
【ProtoBuf 语法详解】Any 类型
服务器·开发语言·c++·protobuf
无忧.芙桃5 小时前
C++11的部分内容(上)
c++
小璐资源网5 小时前
C++中如何正确区分`=`和`==`的使用场景?
java·c++·算法