简体   繁体   English

总是检查malloc的内存?

[英]Always check malloc'ed memory?

I often catch myself doing the following (in non-critical components): 我常常发现自己正在做以下事情(在非关键组件中):

some_small_struct *ptr=(some_small_struct *) malloc(sizeof(some_small_struct));
ptr->some_member= ...;

In words, I allocate dynamically memory for a small structure and I use it directly without checking the malloc'ed pointer. 总之,我为一个小结构分配动态内存,我直接使用它而不检查malloc'ed指针。 I understand there is always a chance that the program won't get the memory it asks for (duh!) but consider the following: 我知道程序总是有可能无法得到它要求的内存(呃!)但请考虑以下内容:

If the program can't even get some memory for a small structure off the heap, maybe there are much bigger problems looming and it doesn't matter after all. 如果程序甚至无法从堆中的小结构中获得一些内存,那么可能会出现更大的问题,而且无关紧要。

Furthermore, what if handling the null pointer exacerbates the precarious situation even more?? 那么,如果处理空指针会加剧岌岌可危的情况呢? (eg trying to log the condition calls even more non-existing resources etc.) (例如,尝试记录条件会调用更多不存在的资源等)

Is my reasoning sane (enough) ? 我的推理是否合理(足够)?

Updated : 更新

  1. A "safe_malloc" function can be useful when debugging and might be useful otherwise 调试时“safe_malloc”函数非常有用,否则可能会有用
  2. +X access can hide the root cause of a NULL pointer +X访问可以隐藏NULL指针的根本原因
  3. On Linux, "optimistic memory allocation" can shadow loomin OOM (Out-Of-Memory) conditions 在Linux上,“乐观内存分配”可以影响loom OOM(Out-Of-Memory)条件

Depends on the platform. 取决于平台。 For instance, on Linux (by default) it does not make much sense to check for NULL: 例如,在Linux上(默认情况下)检查NULL没有多大意义:

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

By default, Linux follows an optimistic memory allocation strategy. 默认情况下,Linux遵循乐观的内存分配策略。 This means that when malloc() returns non-NULL there is no guarantee that the memory really is available. 这意味着当malloc()返回非NULL时,无法保证内存确实可用。 This is a really bad bug. 这是一个非常糟糕的错误。 In case it turns out that the system is out of memory, one or more processes will be killed by the infamous OOM killer. 如果事实证明系统内存不足,臭名昭着的OOM杀手就会杀死一个或多个进程。

In the case of C, it depends on the platform. 在C的情况下,它取决于平台。 If you are on an embedded platform with very little memory, you should alweays check, thouggh what you do if it does fail is more difficult to say. 如果你在一个内存很少的嵌入式平台上,那么你应该检查一下,如果它确实失败你会做什么更难说。 On a modern 32-bit OS with virtual memory, the system will probably become unresponsive and crash before it admits to running out of memory. 在具有虚拟内存的现代32位操作系统上,系统可能会在承认内存不足之前无响应并崩溃。 In this case, the call to malloc never returns, so the utility of checking its value becomes moot. 在这种情况下,对malloc的调用永远不会返回,因此检查其值的实用程序变得没有实际意义。

In the case of C++, you should be using new instead of malloc, in which case an exception will be raised on exhaustion, so there is no point in checking the return value. 在C ++的情况下,您应该使用new而不是malloc,在这种情况下,将在耗尽时引发异常,因此检查返回值没有意义。

I would say No. Using a NULL pointer is going to crash the program (probably). 我会说不。使用NULL指针会导致程序崩溃(可能)。
But detecting it and doing something intelligent will be OK and you may be able to recover from the low memory situation. 但是检测它并做一些智能的事情就可以了,你可以从低内存情况中恢复过来。

If you are doing a big operation set some global error flag and start unwinding the stack and releasing resources. 如果您正在执行大型操作,请设置一些全局错误标志并开始展开堆栈并释放资源。 Hopefully one or more of these resources will be your memory hog and your application will get back to normal. 希望这些资源中的一个或多个将成为您的记忆力,您的应用程序将恢复正常。

This of course is a C problem and handeled automatically in C++ with the help of exceptions and RAII. 这当然是一个C问题,并在例外和RAII的帮助下在C ++中自动处理。
As new will not return NULL there is no point in checking. 由于new不会返回NULL,因此检查没有意义。

Allocations can fail for several reasons. 分配可能由于多种原因而失败。 What you do (and can do) about it depends in part on the allocation failure. 你做(也可以做)的事情部分取决于分配失败。

Being truly out of memory is catastrophic. 真正失去记忆是灾难性的。 Unless you've made a careful plan for this, there's probably nothing you can do. 除非你为此做了一个仔细的计划,否则你可能无能为力。 (For example, you could have pre-allocated all the resources you'd need for an emergency save and shutdown.) (例如,您可以预先分配紧急保存和关闭所需的所有资源。)

But many allocation failures have nothing to do with being out of memory. 但许多分配失败与内存不足无关。 Fragmentation can cause an allocation to fail because there's not enough contiguous space available even though there's plenty of memory free. 碎片可能导致分配失败,因为即使有足够的可用内存,也没有足够的连续空间可用。 The question specifically said a "small structure", so this is probably as bad as true out-of-memory condition. 这个问题具体说是一个“小结构”,所以这可能和真正的内存不足一样糟糕。 (But code is ever-changing. What's a small structure today might be a monster tomorrow. And if it's so small, do you really need memory from the heap or can you get it from the stack?) (但代码是不断变化的。今天的小结构今天可能是一个怪物。如果它太小了,你真的需要堆中的内存还是从堆栈中得到它?)

In a multi-threaded world, allocation failures are often transient conditions. 在多线程世界中,分配失败通常是瞬态条件。 Your modest allocation might fail this microsecond, but perhaps a memory-hogging thread is about to release a big buffer. 你的适度分配可能会失败这个微秒,但也许一个内存占用线程即将释放一个大缓冲区。 So a recovery strategy might involve a delay and retry. 因此,恢复策略可能涉及延迟和重试。

How (and if) you handle allocation failure can also depend on the type of application. 处理分配失败的方式(如果)也取决于应用程序的类型。 If you're writing a complex document editor, and a crash means losing user's work, then it's worth expending more effort to handle these failures. 如果您正在编写复杂的文档编辑器,并且崩溃意味着丢失用户的工作,那么值得花费更多精力来处理这些失败。 If your application is transactional, and each change is incrementally applied to persistent storage, then a crash is only a minor inconvenience to the user. 如果您的应用程序是事务性的,并且每个更改都会逐步应用于持久存储,那么崩溃只会给用户带来轻微的不便。 Even so, logging should be considered. 即便如此,也应考虑采伐。 If you're application is routinely getting allocation failures, you probably have a bug, and you'll need the logs to know about it and track it down. 如果您的应用程序经常出现分配失败,那么您可能有一个错误,并且您需要日志来了解它并跟踪它。

Lastly, you have to think about testing. 最后,你必须考虑测试。 Allocation failures are rare, so the chance that recovery code has been exercised in your testing is vanishingly small--unless you've taken steps to ensure test coverage by artificially forcing failures. 分配失败很少,因此在测试中执行恢复代码的可能性非常小 - 除非您已采取措施通过人为强制失败来确保测试覆盖率。 If you aren't going to test your recovery code, then it's probably not worth writing it. 如果您不打算测试恢复代码,那么可能不值得编写它。

至少我会在那里放置一个assert(ptr != NULL) ,这样你就会得到一个有意义的错误。

Furthermore, what if handling the null pointer exacerbates the precarious situation even more?? 那么,如果处理空指针会加剧岌岌可危的情况呢?

I do not see why it can exacerbate the situation. 我不明白为什么它会加剧这种情况。
Anyway, when writing code for windows ptr->some_member will throw access violation so you will immediately see the problem, therefore I see no reason to check the return value, unless your program has some opportunity to free the memory. 无论如何,在编写windows ptr-> some_member的代码时会抛出访问冲突,所以你会立即看到问题,因此我认为没有理由检查返回值,除非你的程序有机会释放内存。 For platforms that do not handle null-pointers in a good way(throwing exception) it is dangerous to ignore such points. 对于不能以良好方式处理空指针的平台(抛出异常),忽略这些点是危险的。

Assuming that you are running on a Linux/MaxOs/Windows or other virtual memory system, then... the only reason to check the return value from malloc is if you have a strategy for freeing up enough memory to allow the program to continue running. 假设您正在Linux / MaxOs / Windows或其他虚拟内存系统上运行,那么...检查malloc返回值的唯一原因是,您是否有一个释放足够内存以允许程序继续运行的策略。 An informative message will help in diagnosing the problem, but only if your program caused the out-of-memory situation. 信息性信息将有助于诊断问题,但仅限于您的程序导致内存不足的情况。 Usually it is not your program and the only thing that your program can to do help is to exit as quickly as possible. 通常它不是您的程序,您的程序唯一可以帮助的是尽快退出。

assert(ptr != NULL);

will do all of these things. 会做所有这些事情。 My usual strategy is to have a layer around malloc that has this in it. 我通常的策略是在malloc周围有一个包含它的层。

void *my_malloc(size_t size)
{
    void *ptr = malloc ( size );
    assert(ptr != NULL);
    return *ptr;
}

Then you call my_malloc instead of malloc. 然后你调用my_malloc而不是malloc。 During development I use a memory allocation library that is conducive to debugging. 在开发过程中,我使用了一个有助于调试的内存分配库。 After that if it runs out of memory - I get a message. 之后,如果内存不足 - 我收到一条消息。

Yes, having insufficient memeory will almost certatinly presage other failures coming soon. 是的,没有足够的记忆,几乎可以证明其他失败即将到来。 But how sure are you that no corrupt output will occur between the failure to allocate and the final crash? 但是你有多确定在分配失败和最终崩溃之间不会出现损坏的输出?

How sure are you for every program, every time you make an edit. 每次进行编辑时,您对每个程序的确定程度。

Catch your errors so you can know you crashed on time. 抓住你的错误,这样你就可以知道你按时崩溃了。

可以在启动时分配一大块内存,当你遇到内存不足的情况时可以释放它并使用它来优雅地关闭。

I always feel it is important and best to handle the return of malloc or any other system call for that matter. 我一直觉得处理malloc或任何其他系统调用的返回是非常重要和最好的。 Though in modern systems (apart from embedded ones) it's a rare scenario unless and until your code uses too much memory, it's always safer. 虽然在现代系统中(除了嵌入式系统),但这是一种罕见的情况,除非你的代码使用太多内存,否则它总是更安全。

Continuing the code after a system call failure can lead to corruption, crash and what not apart from making your program look bad. 在系统调用失败后继续执行代码可能会导致损坏,崩溃以及除了使程序看起来不好之外的其他问题。

Also, in linux, memory allocated to a process is limited. 此外,在linux中,分配给进程的内存是有限的。 Try creating 1000 threads in a process and allocate some memory in each one of them, then you can easily simulate the low memory condition. 尝试在一个进程中创建1000个线程并在每个线程中分配一些内存,然后您可以轻松地模拟低内存条件。 : ) :)

Always better to check for sys call return values! 总是更好地检查sys调用返回值!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM