需要检查C中malloc返回的指针

时间:2017-09-03 11:55:31

标签: c malloc

假设我的代码中有以下行:

struct info *pinfo = malloc(sizeof(struct info));

通常还有另一行代码,如下所示:

if (!pinfo)
    <handle this error>

但这真的值得吗?特别是如果对象太小,生成的代码来检查它可能需要比对象本身更多的内存。

5 个答案:

答案 0 :(得分:4)

内存耗尽是很少见的,特别是对于只分配数十个字节内存的小型测试程序,尤其是在具有许多GB可用内存的现代系统上。

然而malloc失败非常常见,特别是对于小测试程序。

malloc可能会因两个原因失败:

  1. 没有足够的内存来分配。
  2. malloc检测到内存分配堆乱了,可能是因为您之前的内存分配出了问题。
  3. 现在,事实证明#2始终发生

    而且,事实证明#1也很常见,虽然不是因为没有足够的内存来满足程序员想要做的分配,而是因为程序员意外地将一个非常大的数字传递给malloc ,意外地要求比已知宇宙中更多的记忆。

    所以,是的,事实证明,检查malloc失败是非常好的想法,即使看起来malloc“不能失败”。< / p>

    要考虑的另一件事是,如果你采用快捷方式并且不检查malloc失败怎么办?如果你继续航行并使用malloc给你的空指针,这将导致你的程序立即崩溃,并且会提醒你你的问题以及“内存不足”的消息没有你的手指在骨头上打if(!pinfo)fprintf(stderr, "out of memory\n"),对吧?

    嗯,不。

    根据您的程序无意中使用空指针执行的操作,它可能不会立即崩溃。无论如何,你得到的崩溃,以及“分段违规 - 核心转储”这样的消息并没有告诉你多少,也没有告诉你你的问题在哪里。您可以出于各种原因(特别是在小测试程序中,特别是如果您是初学者不太确定您正在做什么的话)会出现分段违规。您可以花费数小时徒劳地找出程序崩溃的原因,而不会意识到这是因为malloc正在返回一个空指针。所以,当然,你应该总是检查malloc失败,即使在最小的测试程序中也是如此。

    确定要测试哪些错误,与那些“不可能发生”或由于某种原因不值得捕获的错误,通常是一个难题。知道什么是和不值得检查可能需要相当多的经验。但是,真的,任何用C编程很长时间的人都可以强调告诉你:malloc失败肯定值得检查。

    如果你的程序在所有地方都在呼叫malloc,那么检查每一个电话都可能是一个真正令人讨厌的问题。因此,一种流行的策略是使用malloc包装器:

    void *my_malloc(size_t n)
    {
        void *ret = malloc(n);
        if(ret == NULL) {
            fprintf(stderr, "malloc failed (%s)\n", strerror(errno));
            exit(1);
        }
        return ret;
    }
    

    有三种方法可以考虑这个功能:

    1. 每当你进行一些重复的处理时,在整个地方(在这种情况下,检查malloc失败),看看你是否可以将它移到(集中在一个)单个函数中,像这样。
    2. malloc不同,my_malloc不会失败。 从不返回空指针。这几乎是魔术。您可以随时随地调用它,而且您无需检查其返回值。它让你假装你永远不必担心内存不足(这一直是目标)。
    3. 像任何神奇的结果一样,my_malloc的好处 - 它似乎永远不会失败 - 需要付出代价。如果基础malloc失败,my_malloc会立即退出(因为在这种情况下它不能返回),这意味着你的程序的其余部分没有机会清理。如果该程序是一个文本编辑器,并且每当它有一点错误时它打印“内存不足”然后基本上丢弃了用户在过去一小时内编辑的文件,用户可能不会太高兴。因此,您不能在可能丢失数据的生产程序中使用简单的my_malloc技巧。但对于那些不必担心这类事情的程序来说,这是一个巨大的便利。

答案 1 :(得分:3)

如果malloc失败,那么系统可能会内存不足,或者这是您的程序无法处理的其他内容。它应该立即中止,最多记录一些诊断。不处理来自NULL的{​​{1}}将导致您最终处于未定义的行为状态。有人可能会说,由于malloc的失败而不得不中止已经是灾难性的,但只是让它表现出UB属于更糟糕的类别。

答案 2 :(得分:1)

但是如果malloc失败怎么办?您将取消引用NULL指针,即UB(未定义的行为),您的程序将(可能)失败!

有时检查数据正确性的代码比使用它的代码要长:)。

答案 3 :(得分:0)

这很简单,如果你不检查NULL,你最终可能会遇到运行时错误。检查NULL将帮助您避免程序意外崩溃并正常处理错误情况。

答案 4 :(得分:0)

如果你只想快速测试一些算法,那就好了,但知道它可能会失败。例如,在调试器中运行它。

当您将其包含在您的真实世界计划中时,请添加所需的所有错误检查和处理。