我可以依靠malloc返回NULL吗?
我在Unix系统上读到,即使内存实际上不可用, malloc
也可以返回一个非NULL指针,稍后尝试使用内存将触发一个错误。 由于我不能通过检查NULL来捕捉这样的错误,我想知道检查NULL是多么的有用吗?
在一个相关的说明中,Herb Sutter说,处理C ++内存错误是徒劳的,因为在实际发生exception之前,系统就会进入分页的痉挛状态。 这也适用于malloc
吗?
引用Linux手册 :
默认情况下,Linux遵循乐观的内存分配策略。 这意味着当
malloc()
返回非NULL
,不能保证内存真的可用。 这是一个非常糟糕的错误。 如果事实certificate系统内存不足,一个或多个进程将被臭名昭着的OOM杀手杀死。 如果在不希望突然丢失一些随机选取的进程的情况下使用Linux,而且内核版本足够近,则可以使用如下命令closures这种过度使用行为:# echo 2 > /proc/sys/vm/overcommit_memory
您应该检查是否返回NULL
,特别是在32位系统上,因为进程地址空间可能会在RAM之前耗尽:例如在32位Linux上,用户进程可能具有2G-3G的可用地址空间,而不是超过4G的总RAM。 在64位系统上,检查malloc
返回码可能没有用处,但无论如何都可能被认为是最佳实践,它确实使您的程序更具可移植性。 而且,请记住,取消引用空指针肯定会杀死你的进程; 与此相比,一些交换可能不会有太大的伤害。
如果malloc
在尝试分配less量内存时碰巧返回NULL
,那么在尝试从错误状态中恢复时必须谨慎,因为任何后续的malloc
都可能会失败,直到有足够的内存可用。
默认的C ++操作符new
通常是malloc()
使用的相同分配机制的包装。
在Linux上,如果由于内核的重定位策略而导致内存不足,你确实可以不依靠malloc
返回NULL
,但是你仍然应该检查它,因为在某些情况下, malloc
将返回NULL
,例如,当你要求更多的内存在机器中总共可用。 Linux malloc(3)
联机帮助页调用了“非常糟糕的错误”,并包含关于如何closures它的build议。
我从来没有听说过其他Unix变种也会发生这种行为。
至于“寻呼痉挛”,这取决于机器设置。 例如,我倾向于不在笔记本电脑的Linux安装上设置交换分区,因为您担心的确切行为可能会导致硬盘死机。 我仍然会喜欢我运行的C / C ++程序来检查malloc
返回值,给出相应的错误消息,并在可能的时候自行清理。
检查malloc
的返回对你自己来说并没有什么帮助,使你的分配更安全或者更less出错。 如果这是您实施的唯一的testing,它甚至可能是一个陷阱。
当用0
的参数调用时,标准允许malloc
返回一个唯一的地址,这个地址不是一个空指针,而你没有权限访问。 所以,如果你只是testing返回值是0
还是不testingmalloc
, calloc
或者realloc
的参数,你可能会在稍后遇到一个segfault。
这种错误情况(内存耗尽)在“托pipe”环境中相当罕见。 通常情况下,在你遇到这种错误之前,你早已陷入困境。 (但是,如果你正在编写运行时库,是一个内核黑客或火箭build设者,这是不同的,那么testing是非常有意义的。)
然后,人们倾向于用错误条件的复杂捕获来修饰他们的代码,这些错误条件跨越了几行,做了一些类似的事情,这可能会影响代码的可读性。
我认为这个“检查malloc
的回报”被高估了,有时甚至很顽固地辩护。 其他的事情更重要:
- 总是初始化variables。 对于指针variables这是至关重要的,让程序在事情变得糟糕之前很好地崩溃。
struct
未初始化的指针成员是很难find的错误的重要原因。 - 总是检查
malloc
和Co.的参数,如果这是一个像sizof toto
这样的编译时常sizof toto
那么不会有问题,但总是要确保你的向量分配正确地处理了零情况。
检查malloc
返回的一个简单的事情就是用memset(malloc(n), 0, 1)
来包装它。 这只是在第一个字节中写入一个0
,并且如果malloc
出错或者n
开头为0
,则会崩溃。
从另一个angular度来看待这个问题:
“ malloc
可以返回一个非NULL指针,即使内存不是真正可用”并不意味着它总是返回非NULL。 有可能(而且会)是NULL返回(如其他人已经说过的),所以这个检查是必要的。