如何在同一个文件中定义调用函数时在C中模拟函数?

时间:2015-07-01 08:33:10

标签: c linux c++11 gcc cmocka

我正在尝试在C中模拟一个函数,当函数及其调用函数在不同的文件中定义时,mocking工作正常。但是当两个函数(函数本身及其调用者)在同一个文件中定义时,不会调用模拟函数。

案例1:

//test.c

#include <stdio.h>

/*mocked function*/
int __wrap_func() {
   printf("Mock function !!!\n"); 
}

/*caller function*/
int myTest() {
  return func();
}

int main() {
    myTest();
    return 0;
}

//file.c
#include<stdio.h>

/*function need to be mocked*/
int func() {
  printf("Original function !!!\n");
    }

案例2:

//test.c
#include <stdio.h>
extern int myTest();
/*mocked function*/
int __wrap_func() {
  printf("Mock function !!!\n");
}

int main() {
    myTest();
}
//file.c
#include<stdio.h>

/*function need to be mocked*/
int func() {
  printf("Original function !!!\n");
}

/*caller function*/
int myTest() {
  return func();
}

代码编译命令:gcc -Wl, - wrap = func test.c file.c

In Case 1 . Mock function !!!
In Case 2 . Original function !!!

在案例2中,未调用模拟函数。我正在寻找一个解决方案,我可以模拟函数,甚至调用者和被调用的函数都在同一个文件中。

3 个答案:

答案 0 :(得分:3)

使用以两个下划线开头的函数名称是C中的未定义行为

(在您的情况下,我怀疑函数名__wrap_funcfunc修饰名称冲突,但这是推测性的,完全依赖于编译器。)

您应该考虑使用函数指针的解决方案。

答案 1 :(得分:1)

将导致使用--wrap=symbol链接器选项,以便将未定义的符号解析为__wrap_symbol。 在第一种情况下,func是未定义的符号,因此链接器将搜索__wrap_func并调用该函数。 在第二种情况下,链接器会找到myTest,因为它被声明为extern。 当myTest调用func时,它位于同一个翻译单元中,因此不会与作为int func()的文件驻留在同一文件中。所以原来的func是calles而不是包装版本。当调用者和被调用者在同一文件中以及在不同文件中时,您的设计不适合使用模拟函数。 我建议您使用MACROfunction pointer技术解释here

答案 2 :(得分:1)

你不能。

来自the linker documentation

  

- 换行符号       使用符号包装函数。任何未定义的符号引用都将解析为__wrap_symbol。任何未定义的引用   __real_symbol将被解析为符号。这可用于为系统功能提供包装器。应该调用包装函数   __wrap_symbol。如果它想调用系统函数,它应该调用__real_symbol。这是一个简单的例子:

void *
__wrap_malloc (int c)
{
  printf ("malloc called with %ld\n", c);
  return __real_malloc (c);
}
     

如果使用--wrap malloc将其他代码与此文件链接,则对malloc的所有调用都将调用函数__wrap_malloc。该   在__wrap_malloc中调用__real_malloc将调用真正的malloc   功能。您可能也希望提供__real_malloc函数,所以   没有--wrap选项的链接会成功。

这是重要的一部分......

  

如果你这样做,你   不应该将__real_malloc的定义放在同一个文件中   --wrap malloc中调用;如果这样做,汇编器可以在链接器有机会将其包装到malloc之前解析调用。