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

相关推荐
云泽80828 分钟前
C++ 多态入门:虚函数、重写、虚析构及 override/final 实战指南(附腾讯面试题)
开发语言·c++
仰泳的熊猫34 分钟前
题目1535:蓝桥杯算法提高VIP-最小乘积(提高型)
数据结构·c++·算法·蓝桥杯
闻缺陷则喜何志丹1 小时前
【前后缀分解】P9255 [PA 2022] Podwyżki|普及+
数据结构·c++·算法·前后缀分解
消失的旧时光-19432 小时前
智能指针(二):机制篇 —— 移动语义与所有权转移
c++·智能指针
风吹乱了我的头发~3 小时前
Day31:2026年2月21日打卡
开发语言·c++·算法
mjhcsp4 小时前
C++ 后缀平衡树解析
android·java·c++
D_evil__4 小时前
【Effective Modern C++】第六章 lambda表达式:33. 对于auto&&形参使用decltype以及forward它们
c++
-Rane5 小时前
【C++】vector
开发语言·c++·算法
希望之晨5 小时前
c++ 11 学习 override
开发语言·c++·学习
消失的旧时光-19436 小时前
智能指针(四):体系篇 —— 现代 C++ 内存管理全景图
开发语言·c++