在 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
。查看您的平台文档,因为您需要实现更多功能(例如 free
、realloc
、calloc
等)以实现 malloc
替换完成。
虽然不是您问题的完整答案,但您会发现 CppUTest 对于测试 C 代码也非常有用,并且在其模拟功能中包含大部分 malloc/free 库,允许您控制 malloc失败等等。它也非常适合调试内存分配问题,因为它使用调试分配器。
我发现框架文档有点缺乏细节和示例。
当我几年前使用那个框架时 "in anger",我发现有必要实现我自己的模拟 strdup() 函数,我在 CppUTest 源代码中做了这个。
https://cpputest.github.io/mocking_manual.html
我还添加了 DeathHandler 工具,以帮助在测试期间捕获和诊断段错误。
我想模拟 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
。查看您的平台文档,因为您需要实现更多功能(例如 free
、realloc
、calloc
等)以实现 malloc
替换完成。
虽然不是您问题的完整答案,但您会发现 CppUTest 对于测试 C 代码也非常有用,并且在其模拟功能中包含大部分 malloc/free 库,允许您控制 malloc失败等等。它也非常适合调试内存分配问题,因为它使用调试分配器。
我发现框架文档有点缺乏细节和示例。
当我几年前使用那个框架时 "in anger",我发现有必要实现我自己的模拟 strdup() 函数,我在 CppUTest 源代码中做了这个。
https://cpputest.github.io/mocking_manual.html
我还添加了 DeathHandler 工具,以帮助在测试期间捕获和诊断段错误。