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

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

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

想法好吗?

一种可能性 (诚​​然,丑陋但是​​……)是从静态库中提取单个目标文件。 如果您正在调用的函数及其调用的函数位于单独的目标文件中,则可以链接包含需要调用的函数的目标文件,但不能与包含其调用函数的函数相对应。

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

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

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

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

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

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