怎么检测malloc失败?

时间:2011-06-13 01:43:05

标签: c

检查malloc是否未能分配非零内存块的可移植方式是什么?

5 个答案:

答案 0 :(得分:31)

根据Single Unix Specificationmalloc将返回NULL并在失败时设置errno

答案 1 :(得分:15)

我总是这样做:

tok = malloc( sizeof( char ) * ( strlen(tc) + 1 ) );

if( tok == NULL )
{
     /* Malloc failed, deal with it */
}

有些人会tok = (type) malloc( ... ),但你应该投出结果,因为它显然掩盖了一些令人讨厌的错误。我会做一些研究,看看我是否能确切地知道它们是什么。

修改

投射malloc可以隐藏丢失的#include <stdlib.h>

我发现此链接包含一个非常好的解释:

  

http://cboard.cprogramming.com/faq-board/25799-faq-casting-malloc.html

     

“所以当你说这个(char *)malloc(10)

时      

你说你拿走了什么   malloc返回,将其转换为char *,   并将其分配给变量in   问题

     

如果是malloc,这一切都很好   原型正确(通过包括   stdlib.h),定义为   返回void *。

     

当你失败时,问题会出现   包括stdlib.h和编译器   最初假设malloc返回   一个int。真正的问题是,你不要   得到编译器的任何警告。

     

然后你快乐地将那个int转换成一个   char *(通过演员表)。在机器上   其中sizeof(char *)与...不同   sizeof(int),代码很认真   碎。

     

现在,如果你只有char * var =   malloc(10);你错过了   包括,你会得到一个   来自编译器的警告。“

答案 2 :(得分:6)

不确定。可移植的方法是测试malloc(...)是否返回NULL

答案 3 :(得分:6)

您可以在以下情况下检测到失败:

malloc(n)返回NULL

这是检测分配失败的最常见,最可靠的测试。如果你想在POSIX / SUS之外移植,我不相信errno。如果你需要详细信息,比如记录,我会在通话前调零errno,看看它是否有变化,然后记录下来。

malloc(n)返回非NULL地址,该地址不受实际内存支持

触摸它,看看你是否被操作系统杀死了。是的,这可能发生。它被称为内存过度使用,类似于fractional reserve banking。这是操作系统或虚拟机管理程序将地址返回虚拟内存的乐观方法,这些虚拟内存是他们不必实际提供的赌博。这发生在LinuxVMware上。 (虽然请求了pages are only "committed" when they are touched,但我找不到Windows过度使用的任何明确证据。)

接下来的问题是“我如何能够轻松地检测我的程序是否会因访问我从之前信任的malloc获得的地址而崩溃?”一种方法可能是read() a random file into the test area并查看操作系统是否返回EINVAL或等效。

加分,

malloc(0)返回NULL并留下errno未定义

我知道问题是“非零[大小]内存块”,但这很有趣。考虑一个SUS兼容的分配器打算返回非NULL进行零大小的分配(它可以做到这一点),但随后失败,所以它必须返回{{1 }}。它可以尝试设置NULL。这是失败吗?我认为Hoare说我们为这种模棱两可支付了10亿美元。因此,调用errno不可移植,提问者可能知道!

答案 4 :(得分:2)

失败后,

malloc(n)会返回NULL malloc(0) 可能会返回NULL

检测失败:

void* ptr = malloc(n);
if (ptr == NULL && n > 0) Handle_Failure();

注意:

与OP的情况一样:&#34; ...分配非零内存块&#34;,通常代码不能发生0分配请求,因此{{ 1}}不需要测试。

0

有些系统会在失败时设置size_t nstr = strlen(some_string) + 1; void* ptrstr = malloc(nstr); if (ptrstr == NULL) Handle_Failure(); ,但不是全部。由于内存分配失败而设置errno在C11规范中未指定

errno期望malloc(n)为无符号类型n。使用带有负值的size_t肯定会转换为某个大的无符号值,然后可能会使内存分配失败。