检查malloc
是否未能分配非零内存块的可移植方式是什么?
答案 0 :(得分:31)
根据Single Unix Specification,malloc
将返回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。这是操作系统或虚拟机管理程序将地址返回虚拟内存的乐观方法,这些虚拟内存是他们不必实际提供的赌博。这发生在Linux,VMware上。 (虽然请求了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
肯定会转换为某个大的无符号值,然后可能会使内存分配失败。