在 C 中模拟库函数

Mocking library functions in C

我想模拟 c 库的函数,例如 malloc,而不会对原始源文件(使用 malloc 的文件)做太多改动。

我尝试包含一个头文件 "mock.h" 就像

#ifndef MOCK_H_
# define MOCK_H_
# ifdef MOCK_MODE

#  include <sys/types.h>

extern void *my_mock_malloc(size_t n);
void    *malloc(size_t n) __attribute__((weak, alias ("my_mock_malloc")));

# endif /* MOCK_MODE */
#endif /* !MOCK_H_ */

但它给我一个错误

in file included from ...:
/usr/include/stdlib.h:466:14: error: ‘malloc’ aliased to undefined symbol ‘my_mock_malloc’
 extern void *malloc (size_t __size) __THROW __attribute_malloc__ __wur;

GCC alias to function outside of translation unit -AKA- is this even the right tool for the job? gives a partial solution: using the linker I create an alias on a symbol. I can now compile with -Xlinker --defsym "malloc"="my_mock_malloc". The problem is that all my .o files are linked using this option and thus the unit testing framework I use (check) 受到模拟的影响(因此当我创建模拟函数 return NULL 时它接收到的是 SIGSEGV)。

有没有办法在本地执行这种符号别名,这样我就可以让我的测试框架使用真正的 malloc? Os有没有比这个更好的解决方案?

我找到了一个解决方案,它包含一个头文件mock.h,比如

#ifndef MOCK_H_
# define MOCK_H_
# ifdef MOCK_MODE

#  include <sys/types.h>

extern void *my_mock_malloc(size_t n);
#  define malloc(x) (my_mock_malloc(x))

# endif /* MOCK_MODE */
#endif /* !MOCK_H_ */

但我仍然对另一种解决方案感到好奇。

你可以这样做:

#include <stdio.h>
#include <stdlib.h>

#define malloc my_malloc

void *my_malloc(size_t size) {
    printf ("Called my_malloc\n");
    return NULL;
}

int main(void) {
    char * array = malloc(100);
    return 0;
}

程序输出:

Called my_malloc

大多数C语言的实现都将libc的所有符号指定为weak,,即您可以根据需要覆盖它们。试试看!您可以编写自己的名为 malloc 的函数,它会自动替换提供的库 malloc。查看您的平台文档,因为您需要实现更多功能(例如 freerealloccalloc 等)以实现 malloc 替换完成。

虽然不是您问题的完整答案,但您会发现 CppUTest 对于测试 C 代码也非常有用,并且在其模拟功能中包含大部分 malloc/free 库,允许您控制 malloc失败等等。它也非常适合调试内存分配问题,因为它使用调试分配器。

我发现框架文档有点缺乏细节和示例。

当我几年前使用那个框架时 "in anger",我发现有必要实现我自己的模拟 strdup() 函数,我在 CppUTest 源代码中做了这个。

https://cpputest.github.io/mocking_manual.html

我还添加了 DeathHandler 工具,以帮助在测试期间捕获和诊断段错误。