ld报错:motionFactory构造函数未定义,但objdump可检测到该函数
跨语言(D/C++)链接错误排查:继承D类时构造函数未定义引用
问题场景
用D语言编写extern (C++)修饰的motionFactory类,在C中直接构造该类正常,但继承它实现motionGraph时出现链接错误,objdump能检测到D编译生成的构造函数符号,g链接却提示未定义引用。
D语言实现的motionFactory类
extern (C++){ class motionFactory{ public: this(double velocity, double gravity, double angle){ this.velocity = velocity; this.gravity = gravity; this.angle = angle; } } }
C++头文件声明
class motionFactory { public: motionFactory(double velocity, double gravity, double angle); }
C++继承实现的motionGraph类
class motionGraph : public wxBitmap, public motionFactory{ public: motionGraph(double velocity, double gravity, double angle, int width, int height); }
链接错误信息
/usr/bin/ld: motionGraph.o: in function `motionGraph::motionGraph(double, double, double, int, int)': motionGraph.cpp:(.text+0x66): undefined reference to `motionFactory::motionFactory(double, double, double)'
编译命令
gdc -r D/motion.d ballistics.o -o motion.o $(CFLAGS) -lgphobos -J fortran g++ -c gui/motionGraph.cpp -o motionGraph.o $(CFLAGS) $(wxFlags) g++ gui/main.cpp motionGraph.o motion.o mainFrame.o -o guiCalculator -lm $(CFLAGS) $(wxFlags)
objdump结果
D编译文件(motion.o)输出
000000000000039c g F .text 0000000000000047 motionFactory::motionFactory(double, double, double)
C++编译文件(motionGraph.o)输出
0000000000000000 g F .text 0000000000000177 motionGraph::motionGraph(double, double, double, int, int) 0000000000000000 *UND* 0000000000000000 motionFactory::motionFactory(double, double, double) 0000000000000000 w O .data.rel.ro._ZTV11motionGraph 0000000000000108 vtable for motionGraph 0000000000000000 *UND* 0000000000000000 operator new(unsigned long) 0000000000000000 *UND* 0000000000000000 motionFactory::motionFactory(double, double, double)
原因分析与修复方案
核心原因
- 类布局不兼容:D类默认无虚函数时不会生成虚表,但C++子类继承后会生成虚表,导致基类构造函数的调用逻辑变化,符号查找路径异常。
- 链接顺序问题:链接器按传入文件顺序查找符号,引用符号的
motionGraph.o放在定义符号的motion.o前面,会导致符号未找到。
修复步骤
给D类添加虚析构函数,强制生成虚表
修改D类代码:extern (C++){ class motionFactory{ public: this(double velocity, double gravity, double angle){ this.velocity = velocity; this.gravity = gravity; this.angle = angle; } // 添加虚析构函数,对齐C++类布局 ~this() {} } }同步修改C++头文件:
class motionFactory { public: motionFactory(double velocity, double gravity, double angle); virtual ~motionFactory(); }调整链接顺序
将定义符号的motion.o放在motionGraph.o之前,修改最后一条编译命令:g++ gui/main.cpp motion.o motionGraph.o mainFrame.o -o guiCalculator -lm $(CFLAGS) $(wxFlags)验证符号一致性
用nm -C motion.o查看D编译生成的符号,确保与C++期望的motionFactory::motionFactory(double, double, double)完全匹配。
补充说明
直接构造motionFactory正常是因为未涉及继承时的虚表逻辑,符号查找路径简单;但继承后子类构造函数调用基类构造时,链接器对符号的校验逻辑更严格,必须保证基类布局和符号修饰完全符合C++规范。
内容的提问来源于stack exchange,提问作者TCA 166
相关产品推荐
相关产品推荐

