覆盖静态库中定义的C函数

时间:2011-11-03 21:18:22

标签: c gcc g++ cygwin

我有一个C文件的静态库,在Cygwin上用g ++编译。我希望单元测试库中定义的一个函数。该函数调用该库中定义的另一个函数,我希望覆盖依赖项以将其替换为我自己的该函数版本。我无法修改静态库中的内容,因此此解决方案[Override a function call in C]不适用。

通常,我可以编写.cpp文件并包含.c文件,其中包含我想要进行单元测试的函数,这实际上是使用我添加的代码扩展该文件。这是一个我从未用于生产代码的肮脏技巧,但它对于单元测试C文件很方便,因为它使我的测试代码可以访问该C文件中的静态内容。然后,我可以写我的假依赖版本,以及调用我正在测试的函数的单元测试函数。我编译my.cpp来获取my.o,然后将其与静态库链接。从理论上讲,由于链接器已经找到了依赖关系的定义(我提供的那个),因此它不会在库中查找,也不会发生冲突。通常这可行,但现在我得到一个“多重定义”错误,链接器首先找到我的假,然后找到真正的假。我不知道是什么原因造成的,不知道该找什么。我也不能把它归结为一个简单的例子,因为我的简单例子没有这个问题。

想法好吗?

3 个答案:

答案 0 :(得分:5)

一个可能性(诚然,丑陋的,但是......)是从静态库中提取单个目标文件。如果你正在调用的函数和函数它的调用是在单独的目标文件中,你可以链接到包含你需要调用的函数的目标文件,但不能反对包含它调用的函数的文件

这只能提供完整对象文件级别的粒度,因此如果涉及的两个函数都在同一个目标文件中,它将无法工作。如果确实需要让事情发挥作用,并且不介意对相关目标文件进行真正的次要修改,那么可能能够使用二进制编辑器将第二个函数标记为弱外部函数,这意味着它将在没有任何其他具有相同名称的外部函数的情况下使用,但如果提供了另一个函数,则将使用该函数。

后者是否有资格作为“修改库”取决于您的观点。它不是修改库中的代码,而是围绕该代码修改一些目标文件包装器。我的猜测是你宁愿不这样做,但它可能仍然是摆脱原本无法维持的最干净的方式。

答案 1 :(得分:0)

事实证明,链接器发现函数的两个定义的原因是伪造函数的源文件定义了一个变量,该变量在其头文件中是extern'ed。头文件中未解析的外部导致链接器将伪造函数的目标文件(整个事物)链接到库中测试函数的文件。因此,如果没有依赖关系的定义,就不可能提取被测试函数的定义。

我最终做的是类似于Override a function call in C,其中我使用了不同的函数名而不是相同的函数名,并使用预处理器指令来交换这两者。我将预处理程序指令和伪函数放在一个单独的文件中,该文件可以包含在单元测试中,因此不必触及库中的生产代码。另外,如果我想在其他地方为另一个单元测试伪造相同的功能,我可以重新使用新文件。

答案 2 :(得分:0)

根据您的平台和性能要求,您可以使用pin动态修改应用程序,并在运行时将另一个函数替换为另一个函数。

手册中没有直接示例,但您可以轻松修改其中一个示例图钉工具来执行此操作。