代码之家  ›  专栏  ›  技术社区  ›  Pillsy

失败malloc()的单元测试

  •  8
  • Pillsy  · 技术社区  · 16 年前

    对涉及失败代码的代码路径进行单元测试的最佳方法是什么 malloc() ? 在大多数情况下,这可能并不重要,因为你正在做类似的事情

    thingy *my_thingy = malloc(sizeof(thingy));
    if (my_thingy == NULL) {
      fprintf(stderr, "We're so screwed!\n");
      exit(EXIT_FAILURE);
    } 
    

    但在某些情况下,除了死亡,你还有其他选择,因为你已经分配了一些额外的东西用于缓存或其他什么,你可以回收这些内存。

    但是,在这些情况下,您可以尝试从故障恢复 malloc()

    6 回复  |  直到 11 年前
        1
  •  16
  •   Marco Bonelli    8 年前

    malloc()

    1. 读取线程调用的当前执行堆栈
    2. 检查存储在硬盘上的数据库中是否存在堆栈
      1. 如果堆栈不存在,则将堆栈添加到数据库并返回 NULL
      2. 如果堆栈已经存在,则正常分配内存并返回

    然后您只需多次运行单元测试:此系统通过不同的控制路径自动枚举 malloc()

        2
  •  2
  •   Dave    16 年前

    void* special_malloc(size_t bytes) {
      void* ptr = malloc(bytes);
      if(ptr == NULL) {
        /* Do something crafty */
      } else {
        return ptr;
      }
    }
    

    然后,您可以在这里通过为字节传递一些坏值来单元测试这个狡猾的业务。您可以将其放在一个单独的库中,并创建一个模拟库,该库的行为对于您测试调用该库的函数来说非常特殊。

        3
  •  2
  •   Seth    16 年前

    这有点恶心,但是如果你真的想要单元测试,你可以使用#ifdef:

    thingy *my_thingy = malloc(sizeof(thingy));
    #ifdef MALLOC_UNIT_TEST_1
    my_thingy = NULL;
    #endif
    if (my_thingy == NULL) {
      fprintf(stderr, "We're so screwed!\n");
      exit(EXIT_FAILURE);
    }
    

    不幸的是,您必须使用此解决方案重新编译很多内容。

    ulimit ,但要小心。

        4
  •  2
  •   pm100    16 年前

    编写自己的库,通过随机失败或调用真正的malloc(静态链接或显式打开)来实现malloc

        5
  •  1
  •   Roman Nikitchenko    16 年前

    在FreeBSD中,我曾经简单地重载了C库malloc.o模块(符号很弱),并用一个失败概率可控的实现替换了malloc()实现。

    还看 here 在我看来,你似乎需要一套好的工具。至少它们重载malloc()/free()来跟踪泄漏,所以它似乎是添加任何您想要的内容的可用点。

        6
  •  1
  •   Rickard    16 年前

    #include <stdio.h>
    #include <stdlib.h>
    
    #define malloc(x) fake_malloc(x)
    
    struct {
      size_t last_request;
      int should_fail;
      void *(*real_malloc)(size_t);
    } fake_malloc_params;
    
    void *fake_malloc(size_t size) {
      fake_malloc_params.last_request = size;
      if (fake_malloc_params.should_fail) {
        return NULL;
      }
      return (fake_malloc_params.real_malloc)(size);;
    }
    
    int main(void) {
      fake_malloc_params.real_malloc = malloc;
      void *ptr = NULL;
      ptr = malloc(1);
      printf("last: %d\n", (int) fake_malloc_params.last_request);
      printf("ptr: 0x%p\n", ptr);
      return 0;
    }