怎么检测malloc失败?

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

根据单Unix规范 , malloc将返回NULL并在失败时设置errno

我总是这样做:

 tok = malloc( sizeof( char ) * ( strlen(tc) + 1 ) ); if( tok == NULL ) { /* Malloc failed, deal with it */ } 

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

编辑:

转换malloc可以隐藏缺少的#include

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

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

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

你说你接受任何malloc返回,将其转换为char *,并将其分配给相关变量。

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

当您未能包含stdlib.h时,问题就出在了,并且编译器最初假定malloc返回一个int。 真正的问题是,你不要从编译器得到任何警告。

然后你快乐地将那个int转换为char *(通过强制转换)。 在sizeof(char *)与sizeof(int)不同的机器上,代码严重破坏。

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

当然。 可移植的方法是测试malloc(...)返回NULL

您可以在以下时间检测故障

malloc(n)返回NULL

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

malloc(n)返回一个非实际内存支持的非NULL地址

触摸它,看看你是否被操作系统杀死了。 是的,这可能发生。 它被称为内存过度使用 ,类似于部分储备银行业务 。 操作系统或虚拟机管理程序的乐观方法是将地址返回到虚拟内存,而这些虚拟内存是他们不必实际提供的赌博。 这发生在Linux , VMware上 。 (我找不到任何有关Windows过度使用的明确证据,尽管请求的页面只有在被触及时才会“提交” 。)

接下来的问题是“我如何能够轻松地检测我的程序是否会因访问我之前信任的malloc(如青少年迷恋?)而获得的地址崩溃?”。 一种方法可能是将随机文件read()到测试区域 ,看看OS是否返回EINVAL或等效。

加分,

malloc(0)返回NULL并保留errno undefined

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

malloc(n)在失败时返回NULL
malloc(0) 可能返回NULL

检测失败:

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

笔记:

与OP的情况一样:“…分配非零内存块”,通常代码不能发生0分配请求,因此不需要0测试。

 size_t nstr = strlen(some_string) + 1; void ptrstr = malloc(nstr); if (ptrstr == NULL) Handle_Failure(); 

有些系统在故障时设置errno ,但不是全部。 由于内存分配失败而设置的errno 在C11规范中指定。

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