怎么检测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
肯定会转换为某个大的无符号值,然后可能会使内存分配失败。