我应该检查 malloc() 是不是成功?

Posted

技术标签:

【中文标题】我应该检查 malloc() 是不是成功?【英文标题】:Should I check if malloc() was successful?我应该检查 malloc() 是否成功? 【发布时间】:2015-01-06 01:25:11 【问题描述】:

是否应该在每个malloc() 之后检查一次是否成功? malloc() 是否有可能失败?然后会发生什么?

在学校我们被告知我们应该检查,即:

arr = (int) malloc(sizeof(int)*x*y);
if(arr==NULL)
    printf("Error. Allocation was unsuccessful. \n");
    return 1;

这方面的做法是什么?我可以这样做吗:

if(!(arr = (int) malloc(sizeof(int)*x*y))
    <error>

【问题讨论】:

理论上是的。实际上,如果 malloc 失败,操作系统可能即将崩溃。 PS:你的第二个例子比第一个更难阅读,应该被代码审查拒绝。 arr = (int) malloc(...) 错误,malloc 返回一个指针。除此之外:是的,您应该检查它是否失败,因为它可能会失败。 Also, casting its return value is harmful. 1.你不需要演员表。 2. 是的,检查 - 为什么不 @SteveWellens 我会说在理论上和实践中都是肯定的,尤其是在分配大缓冲区时。 @AlexD - 是的。但是如果你分配的缓冲区太大以至于 malloc 可能会失败,那么我会说重新设计是为了。 【参考方案1】:

这主要只是增加了现有的答案,但我知道你来自哪里,如果你做了很多内存分配,你的代码最终看起来很丑陋,所有的 malloc 错误检查。

就我个人而言,我经常使用永远不会失败的小型 malloc 包装器来解决这个问题。除非您的软件是一个弹性的、安全的关键系统,否则无论如何您都无法有效地解决 malloc 失败的问题,因此我建议您这样做:

static inline void *MallocOrDie(size_t MemSize)

    void *AllocMem = malloc(MemSize);
    /* Some implementations return null on a 0 length alloc,
     * we may as well allow this as it increases compatibility
     * with very few side effects */
    if(!AllocMem && MemSize)
    
        printf("Could not allocate memory!");
        exit(-1);
    
    return AllocMem;

这至少可以确保您收到错误消息并清除崩溃,并避免所有大量错误检查代码。

对于可能失败的函数的更通用的解决方案,我也倾向于实现一个简单的宏,例如:

#define PrintDie(...) \
    do \
     \
    fprintf(stderr, __VA_ARGS__); \
    abort(); \
     while(0)

然后允许您将函数运行为:

if(-1 == foo()) PrintDie("Oh no");

这为您提供了一个衬里,在启用适当检查的同时再次避免了大容量。

【讨论】:

您的PrintDie 应该调用abort,而不是exit。因为它更容易调试(在 Linux 上,您甚至会得到一个 core 转储,您可以使用 gdb 进行事后分析) @BasileStarynkevitch 谢谢,完全忘记了 abort,现在更改示例以使用它。 if(NULL == AllocMem) 是错误的测试。使用MemSize == 0,接收malloc() 返回值NULL 兼容行为,而不是分配失败。更改为 if(NULL == AllocMem &amp;&amp; MemSize != 0) 可以解决此问题。 @chux 你说得对,这是大多数实现的理想行为,正如它所说的(在 C99 和 C11 中),标准中有点棘手:“如果请求的空间大小是零,行为是实现定义的”(7.22.3 P1,ISO C11)。但是,您建议的是许多编译器中的常见实现,因此我将在代码中添加一个带有注释的检查。谢谢。 @Ayxan 它看起来像。虽然我以前从未见过 xmalloc,因为我从未在 BSD 上开发过。看起来像一个有用的功能。谢谢你的信息。【参考方案2】:

无需投射malloc()。可以,但是需要检查malloc() 是否成功。 假设malloc() 失败,并且您试图访问指针,认为内存分配会导致崩溃,因此最好在访问指针之前捕获内存分配失败。

int *arr = malloc(sizeof(*arr));
if(arr == NULL)

printf("Memory allocation failed");
return;

【讨论】:

在迂腐的注解中,这个答案提倡“检查 malloc() 是否成功”——这是一个好主意。但随后它显示了如何检查malloc(sizeof(int)) 的结果,而不是 OP 的malloc(sizeof(int)*x*y)。对NULL 进行测试对于这个sizeof(int) 来说就足够了,但对于OP 的sizeof(int)*x*y 来说是错误的。如果x*y --> 0,NULL 返回是兼容代码,并不表示内存分配。最好使用if(arr == NULL &amp;&amp; x != 0 &amp;&amp; y != 0)

以上是关于我应该检查 malloc() 是不是成功?的主要内容,如果未能解决你的问题,请参考以下文章

如何检查解密是不是成功?

如何检查是不是使用 malloc 或 new 分配了内存

当内核使用过度使用内存时,是不是需要在分配内存后检查 NULL

NodeJs - 检查子进程是不是成功启动

检查指针是不是指向堆上分配的内存

如何检查 SOCKS 服务器是不是正常工作?