我可以依赖malloc返回NULL吗?

我可以依赖malloc返回NULL吗?,c,memory,error-handling,malloc,C,Memory,Error Handling,Malloc,我了解到,在Unix系统上,malloc可以返回非空指针,即使内存实际上不可用,稍后尝试使用内存也会触发错误。由于我无法通过检查NULL来捕获这样的错误,我想知道检查NULL到底有多有用 在一个相关的注释中,Habor萨特说处理C++内存错误是徒劳的,因为系统将在实际发生异常之前长时间地进入寻呼的痉挛状态。这也适用于malloc吗?引用: 默认情况下,Linux遵循乐观的内存分配策略。这意味着当malloc()返回非NULL时,没有 保证 内存确实可用。这是一个非常糟糕的错误。在系统内存不足的情

我了解到,在Unix系统上,
malloc
可以返回非空指针,即使内存实际上不可用,稍后尝试使用内存也会触发错误。由于我无法通过检查NULL来捕获这样的错误,我想知道检查NULL到底有多有用

在一个相关的注释中,Habor萨特说处理C++内存错误是徒劳的,因为系统将在实际发生异常之前长时间地进入寻呼的痉挛状态。这也适用于malloc吗?

引用:

默认情况下,Linux遵循乐观的内存分配策略。这意味着当
malloc()
返回非
NULL
时,没有 保证 内存确实可用。这是一个非常糟糕的错误。在系统内存不足的情况下,一个或多个 过程将是 被臭名昭著的杀人凶手杀死。如果Linux是在不太希望突然丢失的情况下使用的 随机的 选择进程,而且内核版本足够新,可以关闭这种过度交付行为 使用如下命令:

# echo 2 > /proc/sys/vm/overcommit_memory
您应该检查
NULL
return,特别是在32位系统上,因为进程地址空间可能在RAM之前就耗尽了:例如,在32位Linux上,用户进程的可用地址空间可能是2G-3G,而不是超过4G的总RAM。在64位系统上,检查
malloc
返回代码可能是无用的,但无论如何都可能被认为是良好的做法,并且它确实使您的程序更具可移植性。而且,请记住,取消对空指针的引用肯定会扼杀您的进程;与此相比,一些交换可能不会造成太大伤害

如果在尝试仅分配少量内存时
malloc
恰好返回
NULL
,则在尝试从错误状态恢复时必须小心,因为任何后续
malloc
也可能失败,直到有足够的内存可用


默认的C++操作符<代码>新< /C>通常是在 MalCube()//Cuff.< /P> < P>上的相同分配机制的包装上,如果内核的过度分配策略,如果内存不足,则您确实不能依赖于<代码> MalOC/<代码>返回<代码> null < /代码>但是您仍然应该检查它,因为在某些情况下,

malloc
将返回
NULL
,例如,当您请求的内存超过机器的总可用内存时。Linux
malloc(3)
manpage将过度分配称为“一个非常糟糕的bug”,并包含关于如何关闭它的建议

我从来没有听说过这种行为也发生在其他Unix变体中


至于“分页间歇”,这取决于机器设置。例如,我倾向于不在笔记本电脑Linux安装上设置交换分区,因为您担心的确切行为可能会杀死硬盘。我仍然希望我运行的C/C++程序检查malloc返回值,给出适当的错误消息,并在可能的情况下进行清理。

从另一个角度来看:


malloc
可以返回非空指针,即使内存实际上不可用”并不意味着它总是返回非空指针。在某些情况下,可能(也将)返回NULL(正如其他人已经说过的),因此此检查是必要的。

检查malloc的返回本身并不能帮助您使分配更安全或更不容易出错。如果这是您实现的唯一测试,那么它甚至可能是一个陷阱

当使用
0
参数调用时,该标准允许
malloc
返回一种唯一的地址,该地址不是空指针,但您无权访问。因此,如果您只测试返回值是否为
0
,而不测试
malloc
calloc
realloc
的参数,您可能会在很久以后遇到segfault

这种错误情况(内存耗尽)在“托管”环境中非常罕见。通常,在你遇到这种错误之前,你已经有麻烦了。(但是,如果您正在编写运行库,那么您是内核黑客还是火箭构建者,这是不同的,在那里测试非常有意义。)

然后,人们倾向于用跨越几行的错误条件的复杂捕获来装饰他们的代码,做
perror
之类的事情,这可能会影响代码的可读性

我认为这种“检查malloc的返回”被高估了很多,有时甚至很武断地进行辩护。其他事情要重要得多:

  • 总是初始化变量,总是。对于指针变量,这是至关重要的, 让程序在事情变得太糟糕之前很好地崩溃。
    struct
    s中未初始化的指针成员是导致难以找到的错误的重要原因
  • 始终检查
    malloc
    和Co的参数。如果这是编译 时间常数,如
    sizof toto
    不会有问题,但是 始终确保向量分配正确处理零情况

检查
malloc
返回的一个简单方法是使用类似
memset(malloc(n),0,1)
的东西来结束它。在第一个字节中,如果写了<代码> 0代码>代码,如果<错误>代码> n>代码> <代码> 0代码>,则我认为你不应该在C++中使用Maloc:@ LC817,如果你用C接口编写代码(即C要用C++写的函数),你只应该使用MALOC。C代码负责释放内存。@WTP感谢这个精度。虽然,我不知道这里的情况是否如此。@Dror K.,我不明白赏金和quic的目的