【问题标题】:Mocking library functions in C在 C 中模拟库函数
【发布时间】:2017-05-24 20:40:51
【问题描述】:

我想模拟 c lib 的函数,例如 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? 给出了部分解决方案:使用链接器我在符号上创建别名。我现在可以使用-Xlinker --defsym "malloc"="my_mock_malloc" 进行编译。问题是我的所有.o 文件都使用此选项链接,因此我使用的单元测试框架(check)受到模拟的影响(因此当我让我的模拟函数返回NULL 时它收到的是 SIGSEGV )。

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

【问题讨论】:

    标签: c testing linker mocking


    【解决方案1】:

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

    【讨论】:

    • 我尝试从我的答案中删除#define,并将函数重命名为malloc。它编译干净但挂起。
    • 您是否也实现了所有其他需要的功能?你在哪个平台上工作?
    • 你会在我的回答中看到我做了什么。 my_malloc 打印一条消息说它已被调用,并返回 NULL。该示例中没有其他需要的功能。当我删除 #include &lt;stdlib.h&gt;#define 并将函数重命名为 malloc 时,它编译但没有运行 - 挂起。 MSVC 2009.
    • 那是因为 GNU printf 在内部调用了 malloc!你得到一个无限循环。同样,您也必须覆盖其他函数,否则会发生怪异行为。
    • Ahhhhh 我只测试了#define 以供本地使用。但我想知道为什么printf 在我原来的答案中起作用(而 Gme 是 Gnot Gnu)-;)
    【解决方案2】:

    我找到了一个解决方案,即包含一个头文件mock.h like

    #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_ */
    

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

    【讨论】:

      【解决方案3】:

      你可以这样做:

      #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
      

      【讨论】:

        【解决方案4】:

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

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

        几年前,当我“愤怒地”使用该框架时,我发现有必要实现我自己的模拟 strdup() 函数,我在 CppUTest 源代码中完成了该函数。

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

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

        【讨论】:

          猜你喜欢
          • 2011-07-18
          • 1970-01-01
          • 1970-01-01
          • 2013-02-23
          • 1970-01-01
          • 1970-01-01
          • 2017-06-10
          • 1970-01-01
          • 2018-02-01
          相关资源
          最近更新 更多