我正在开发一个小型库,我不想在任何可能出现的地方处理分配错误,因此我编写了一个包装器,malloc()如果发生错误,它会终止程序(暂时)。
void *cstr_malloc(size_t size)
{
void *buf = malloc(size);
if (!buf)
{
fprintf(stderr, "Allocation error, terminating\n");
exit(2);
}
return buf;
}
Run Code Online (Sandbox Code Playgroud)
那里没什么特别的。然而现在,我注意到 clang 静态分析器(至少在 Xcode 中)并没有像以前那样捕获明显的泄漏。
如果我做这样的事情:
void foo(void)
{
void *p = malloc(100);
}
Run Code Online (Sandbox Code Playgroud)
它自然会告诉我p可能会泄漏内存。
然而,随着
void foo(void)
{
void *p = malloc(100);
void *q = cstr_malloc(100);
}
Run Code Online (Sandbox Code Playgroud)
它只报告 正在泄漏p,但不报告q正在泄漏。
这就说得通了; 它无法知道程序可能在哪里分配内存并仍然在合理的时间内对其进行分析。如果我内联它,它可以很好地处理我的分配器,因此它可以看到它,但除此之外,它看不到。
有什么方法可以告诉分析器我有一个返回新分配的内存的函数吗?某些属性,类似__attribute__((malloc))或类似?
当然,我可以只内联该函数,但我还有很多其他类似地分配内存的函数,内联所有这些函数会出现问题。
经过几个小时的谷歌搜索后,我找到了至少看起来像是一个解决方案。诀窍确实是使用属性,但不是__attribute__((malloc))。
我需要的属性是ownership_returns(malloc). 使用它,我会收到警告,至少对于这个功能。
__attribute__((ownership_returns(malloc)))
void *cstr_malloc(size_t size);
Run Code Online (Sandbox Code Playgroud)
参见https://godbolt.org/z/MEfvThKnW
不幸的是,我的喜悦是短暂的。如果我使用ownership_returns(malloc),那么分析器将假设内存也未初始化,但情况并非总是如此。我不知道如何暗示我返回必须释放的内存,但不是未初始化的内存。
由于clang可以找出 的情况calloc(),因此也可能有一种方法可以为我的函数做到这一点,但我还没有找到。
下面是一个示例,说明如何clang处理从我自己的函数返回的内存calloc()以及它对来自我自己的函数的内容的看法:https://godbolt.org/z/P45o691Tx