基于已编译目标文件的C++测试:替换函数实现方法咨询
C++测试桩函数创建问题解答
问题1:使用已编译的A.o文件时,能否为测试中的getValue()提供新定义?
可以实现,核心是利用链接器的符号重定向机制(以GCC/Clang为例):
- 编译测试代码时添加链接器选项:
-Wl,--wrap=getValue - 在测试代码中实现桩函数
__wrap_getValue,链接器会自动将所有对getValue的调用重定向到这个桩函数;如果需要调用原函数,还可以通过__real_getValue访问A.o中的原实现。
原理:原getValue()是全局强符号,直接定义同名函数会引发链接冲突,而--wrap选项通过符号重命名规避冲突,实现调用逻辑的替换。
问题2:链接B.o文件时,如何为B::get()提供不同定义?
以下是几种可行的方法:
方法1:链接器--wrap重定向
C++成员函数会经过编译器名字修饰生成唯一符号(例如GCC中B::get()会被修饰为_ZN1B3getEv),可针对修饰后的符号使用--wrap选项:
- 编译测试代码时添加:
-Wl,--wrap=_ZN1B3getEv - 实现桩函数
__wrap__ZN1B3getEv,需保证函数的参数、返回值类型与原函数完全一致。
缺点:符号修饰规则依赖编译器,跨编译器兼容性较差。
方法2:动态链接下的LD_PRELOAD(Linux平台)
若测试程序采用动态链接:
- 编写一个共享库,在其中实现名字修饰后的
B::get()函数(签名与原函数一致) - 运行测试时通过
LD_PRELOAD=./your_stub.so ./test_program加载该共享库,动态链接器会优先使用共享库中的函数定义。
方法3:修改原代码为多态类(允许修改原代码时)
如果可以修改类B的定义,将get()声明为虚函数:
class B { public: virtual void get(); };
之后在测试代码中创建B的子类,重写get()方法,测试时使用子类对象即可替换原有实现。
方法4:结合测试桩框架(如GMock)
若使用Google Test/GMock这类测试框架,可通过Mock类实现替换,但前提是原类B的get()为虚函数(或可修改原代码添加虚函数),否则需要配合链接器技巧一起使用。
内容的提问来源于stack exchange,提问作者SathutaPutha
相关产品推荐
相关产品推荐

