总是检查malloc的内存?

jld*_*ont 22 c architecture system

我常常发现自己正在做以下事情(在非关键组件中):

some_small_struct *ptr=(some_small_struct *) malloc(sizeof(some_small_struct));
ptr->some_member= ...;
Run Code Online (Sandbox Code Playgroud)

总之,我为一个小结构分配动态内存,我直接使用它而不检查malloc'ed指针.我知道程序总是有可能得不到它所要求的内存(呃!)但请考虑以下内容:

如果程序甚至无法从堆中的小结构获得一些内存,那么可能会出现更大的问题,而且它毕竟无关紧要.

那么,如果处理空指针会加剧岌岌可危的情况呢?(例如,尝试记录条件会调用更多不存在的资源等)

我的推理是否合理(足够)?

更新:

  1. 调试时"safe_malloc"函数非常有用,否则可能会有用
  2. +X 访问可以隐藏NULL指针的根本原因
  3. 在Linux上,"乐观内存分配"可以影响loom OOM(Out-Of-Memory)条件

Nem*_*vic 19

取决于平台.例如,在Linux上(默认情况下)检查NULL没有多大意义:

http://linux.die.net/man/3/malloc

默认情况下,Linux遵循乐观的内存分配策略.这意味着当malloc()返回非NULL时,无法保证内存确实可用.这是一个非常糟糕的错误.如果事实证明系统内存不足,臭名昭着的OOM杀手就会杀死一个或多个进程.

  • 当地址空间已满时,Malloc仍然可以返回NULL. (6认同)

小智 11

在C的情况下,它取决于平台.如果你在一个内存很少的嵌入式平台上,那么你应该检查一下,如果它确实失败了,你会怎么做更难说.在具有虚拟内存的现代32位操作系统上,系统可能会在承认内存不足之前无响应并崩溃.在这种情况下,对malloc的调用永远不会返回,因此检查其值的实用程序变得没有实际意义.

在C++的情况下,您应该使用new而不是malloc,在这种情况下,将在耗尽时引发异常,因此检查返回值没有意义.

  • 但在C案例中你应该经常检查.没有反应和可恢复比崩溃更好. (4认同)
  • "在具有虚拟内存的现代32位操作系统上,系统可能会在承认内存不足之前变得无响应并崩溃.在这种情况下,对malloc的调用永远不会返回,因此检查其值的实用程序变得毫无意义. " 这根本不是真的,malloc可能因为地址空间中没有足够的(连续)内存而失败,这并不意味着系统内存不足:实际上32位操作系统上的虚拟地址空间已经上升到4 GB宽,而物理内存可以更多,不计算交换空间.所以,检查返回值. (3认同)
  • @Martin 至少在类似 UNIX 的操作系统上,内存访问冲突可能比干净退出要好,因为那样你会得到一个核心转储。 (2认同)
  • @Mattin核心也会告诉你内存不足的地方,假设你在malloc之后立即使用指针,就像OP所说的那样. (2认同)

Mar*_*ork 7

我会说不.使用NULL指针会导致程序崩溃(可能).
但是检测它并做一些智能的事情就可以了,你可以从低内存情况中恢复过来.

如果您正在执行大型操作,请设置一些全局错误标志并开始展开堆栈并释放资源.希望这些资源中的一个或多个将成为您的记忆力,您的应用程序将恢复正常.

这当然是一个C问题,并在例外和RAII的帮助下在C++中自动处理.
由于new不会返回NULL,因此检查没有意义.


Adr*_*thy 7

分配可能由于多种原因而失败.你做(也可以做)的事情部分取决于分配失败.

真正失去记忆是灾难性的.除非你为此做了一个仔细的计划,否则你可能无能为力.(例如,您可以预先分配紧急保存和关闭所需的所有资源.)

但许多分配失败与内存不足无关.碎片可能导致分配失败,因为即使有足够的可用内存,也没有足够的连续空间可用.这个问题具体说是一个"小结构",所以这可能和真正的内存不足一样糟糕.(但代码是不断变化的.今天的小结构今天可能是一个怪物.如果它太小了,你真的需要堆中的内存还是从堆栈中得到它?)

在多线程世界中,分配失败通常是瞬态条件.你的适度分配可能会在这微秒内失败,但也许一个内存占用线程即将释放一个大缓冲区.因此,恢复策略可能涉及延迟和重试.

处理分配失败的方式(如果)也取决于应用程序的类型.如果您正在编写复杂的文档编辑器,并且崩溃意味着丢失用户的工作,那么值得花费更多精力来处理这些失败.如果您的应用程序是事务性的,并且每个更改都会逐步应用于持久存储,那么崩溃只会给用户带来轻微的不便.即便如此,也应考虑采伐.如果您的应用程序经常出现分配失败,那么您可能有一个错误,并且您需要日志来了解它并跟踪它.

最后,你必须考虑测试.分配失败很少,因此在测试中执行恢复代码的可能性非常小 - 除非您已采取措施通过人为强制失败来确保测试覆盖率.如果您不打算测试恢复代码,那么可能不值得编写它.