3

我正在使用 C 语言在 Unix/Linux 中工作。我对内存分配的工作原理有基本的了解,足以知道如果我 malloc() 然后 free(),我不太可能真正释放整个页面。因此,如果我在 free() 之前和之后使用 getrusage(),我不太可能会看到任何区别。

我想为一个破坏数据结构的函数编写一个单元测试,以查看所涉及的内存区域实际上已被释放。我对依赖操作系统的解决方案持开放态度,在这种情况下,我的主要平台是

Linux beast 3.2.0-23-generic #36-Ubuntu SMP Tue Apr 10 20:39:51 UTC 2012 x86_64 x86_64 x86_64 GNU/Linux

以 OS X 和FreeBSD作为辅助。如果有一种解决方案可以使检查 free() 相对容易,我也愿意更换 malloc()。

需要明确的是,我正在测试一个删除大型数据结构的例程,并且我想确保所有分配的区域都被实际释放,本质上是一个单元测试,特定单元没有基本的内存泄漏. 我将假设 free() 完成了它的工作,我只是确保我的代码实际上在它负责的所有分配区域上调用 free。

在这种特殊情况下,它是一个树结构,对于树中的每条数据,该结构负责调用删除存储在树中的数据的例程,这可能是其他一些任意的事情......

4

4 回答 4

2

我不想再这样做了,但是经过一夜的睡眠后,我找到了一个明确的答案,它来自 SVID(有人甚至记得 System V 吗?),但它被合并到 Linux 上的 glibc 中,可能是通过它在 dlmalloc 中的使用;因此它可以通过使用 dlmalloc() 作为替代 malloc 的替代品在其他系统上使用。

使用常规

struct mallinfo mallinfo(void);

和 struct mallinfo 是

struct mallinfo
{
  int arena;    /* non-mmapped space allocated from system */
  int ordblks;  /* number of free chunks */
  int smblks;   /* number of fastbin blocks */
  int hblks;    /* number of mmapped regions */
  int hblkhd;   /* space in mmapped regions */
  int usmblks;  /* maximum total allocated space */
  int fsmblks;  /* space available in freed fastbin blocks */
  int uordblks; /* total allocated space */
  int fordblks; /* total free space */
  int keepcost; /* top-most, releasable (via malloc_trim) space */
};

特别是 arena 和 uordblks 将为您提供 malloc() 分配的字节数,与使用 sbrk() 或 mmap() 从操作系统请求的页面大小无关,这些页面由 arena 和 hblkhd 给出。

于 2012-07-11T16:10:49.650 回答
2

我最好的建议是使用valgrind.

他们为 malloc 和 free 制作包装器,并比使用自制系统更好地向您展示内存泄漏。他们捕捉到了所有其他类型的错误,这些错误不容易被单元测试发现和测试,比如未初始化的变量。

因此,请始终使用 valgrind 运行您的测试,并制定所有测试都通过并且 valgrind 没有显示错误和未分配内存的成功标准。

PS:如果您已经有一点代码库,开始可能会有点痛苦,但是如果您花时间修复所有 valgrind 错误,您的测试和系统都会更加可靠!

于 2012-12-01T11:20:11.850 回答
1

您可以用于各种内存泄漏调试的一个技巧是简单地增加规模,直到问题更加突出。执行一个malloc/free循环,然后捕获 的结果getrusage(),然后再执行 1000 个malloc/free循环,并确保您的进程实际上并未分配更多内存。通过泄漏其中的 1000 个,您可以将问题的规模扩大到突出的程度。

如果您想要更具确定性(但更具侵入性)的东西,您可以覆盖malloc()free()跟踪分配并观察来自测试工具的跟踪数据。您可以找到几个调试 malloc 库的示例来向您展示它是如何完成的。

于 2012-07-11T00:03:58.560 回答
-1

最简单的方法是为 malloc 和 free 制作包装器。如果您使用真正的 malloc 和 free 那么可能会发生以下情况:

  1. 你分配内存
  2. 你用那段记忆做点什么
  3. 你释放内存
  4. 操作系统中的其他人,甚至您自己的代码中的其他内容,都需要内存,并且操作系统会将该内存分配到其他地方,因为它现在是免费的
  5. 你测试看看内存是否空闲,它不是,但你认为它应该是,所以你得到一个错误的测试失败。
于 2012-07-11T00:03:43.153 回答