我已经看到很多代码在进行分配时检查NULL指针。这使代码变得冗长,如果没有一致地完成,只有当程序员感觉到它时,甚至不能确保程序在地址空间用完时不会崩溃。此外,如果程序无法进行更多分配,那么无论如何都无法完成其功能,对吧?
所以我的问题是,对于大多数程序来说,根本不检查并且如果内存耗尽会让程序崩溃,这不是更好吗?至少代码更具可读性。
注意
我说的是在现代计算机上运行的桌面应用程序(至少2 GB的地址空间),而且绝对不会运行航天飞机,生命支持系统或BP的石油平台。最重要的是,我在谈论使用malloc但从未真正超过5 MB内存使用量的程序。
答案 0 :(得分:11)
始终检查返回值,但为了清楚起见,将malloc()
包装在永不返回NULL
的函数中是很常见的:
void *
emalloc(size_t amt){
void *v = malloc(amt);
if(!v){
fprintf(stderr, "out of mem\n");
exit(EXIT_FAILURE);
}
return v;
}
然后,您可以使用
char *foo = emalloc(56);
foo[12] = 'A';
没有内疚。
答案 1 :(得分:8)
是的,您应该检查malloc
的空返回值。即使您无法从内存分配失败中恢复,也应该明确退出。继续进行内存分配成功,会使应用程序处于不一致状态,并可能导致应该避免的“未定义行为”。
例如,您可能最终将不一致的数据写入外部存储,这可能会妨碍下次运行应用程序的能力。以更加可控的方式快速退出会更安全。
许多想要在分配失败时退出的应用程序在检查返回值并在失败时明确中止的函数中包装malloc
。
可以说,这是C ++默认new
方法在分配失败时抛出异常的一个优点。它不需要努力退出内存分配失败。
答案 2 :(得分:7)
与Dave的上述方法类似,但添加了一个自动通过的宏 我们的分配例程的文件名和行号,以便我们可以报告 发生故障时的信息。
#include <stdio.h>
#include <stdlib.h>
#define ZMALLOC(theSize) zmalloc(__FILE__, __LINE__, theSize)
static void *zmalloc(const char *file, int line, int size)
{
void *ptr = malloc(size);
if(!ptr)
{
printf("Could not allocate: %d bytes (%s:%d)\n", size, file, line);
exit(1);
}
return(ptr);
}
int main()
{
/* -- Set 'forceFailure' to a non-zero value in order to observe
how 'zmalloc' behaves when it cannot allocate the
requested memory -- */
int bytes = 10 * sizeof(int);
int forceFailure = 0;
int *anArray = NULL;
if(forceFailure)
bytes = -1;
anArray = ZMALLOC(bytes);
free(anArray);
return(0);
}
答案 3 :(得分:2)
但是如果你没有记录malloc失败的地方,则要进行故障排除要困难得多。
无法在第XX行分配内存,而不仅仅是崩溃。
答案 4 :(得分:1)
你一定要检查malloc的返回值。有助于调试,代码变得健壮。
答案 5 :(得分:1)
在托管环境中,错误检查malloc
的返回现在没有多大意义。大多数机器的虚拟地址空间为64位。你需要花很多时间来消耗它。您的程序很可能在完全不同的地方失败,即当您的物理+交换内存耗尽时。在此之前它会显示完全荒谬的性能,因为它只是交换,用户在你到达之前很久就会触发Cntrl-C
。
在空指针引用上“很好地”Segfaulting将是一个明确的点,以查看调试器中的事情失败。但在我的实践中,我从未见过失败的malloc
作为原因。
对嵌入式系统进行编程时,图像会完全改变。你肯定应该检查失败的malloc
。
编辑:在编辑问题后澄清一下。那里描述的那种程序/系统显然不是“嵌入式”的。在那里描述的情况下,我从未见过malloc
失败。
答案 6 :(得分:0)
我想补充一点,即使您认为边缘情况安全或不能导致其他问题而不是崩溃,也应始终检查边缘情况。可以利用空指针取消引用(http://uninformed.org/?v=4&a=5&t=sumry)。