安全的malloc/realloc:将调用包装成宏吗?

7
我希望能将malloc/realloc方法的调用封装到一个宏中,如果这个方法返回NULL,则停止程序。请问下面的宏是否安全可靠?
#define SAFEMALLOC(SIZEOF) (malloc(SIZEOF) || (void*)(fprintf(stderr,"[%s:%d]Out of memory(%d bytes)\n",__FILE__,__LINE__,SIZEOF),exit(EXIT_FAILURE),0))
char* p=(char*)SAFEMALLOC(10);

代码可以编译,使用 SAFEMALLOC(1UL)SAFEMALLOC(-1UL) 可以正常运行,但这样做是否安全呢?


3
为什么要用宏,为什么不使用函数?这样你就可以得到一个有用的结果来返回这个“表达式”。 - CB Bailey
请注意,当调用失败时,SIZEOF会被评估两次(虽然程序退出并不是灾难,但仍然需要注意)。 - Kninnug
强制转换结果并不能使其更安全,不过... - wildplasser
这些不是我的源代码,我想避免创建一些新文件(memory.c,memory.h),我知道作者想避免调用其他函数(为科学C程序进行微优化)。 - Pierre
3个回答

14
static void* safe_malloc(size_t n, unsigned long line)
{
    void* p = malloc(n);
    if (!p)
    {
        fprintf(stderr, "[%s:%ul]Out of memory(%ul bytes)\n",
                __FILE__, line, (unsigned long)n);
        exit(EXIT_FAILURE);
    }
    return p;
}
#define SAFEMALLOC(n) safe_malloc(n, __LINE__)

6
不,它已经失效了。
它似乎假设布尔或运算符 || 如果被认为是 true,就会返回它的参数,但实际上并非如此。
C 语言的布尔运算符始终生成整数 1 或 0,它们不会生成任何输入值。

3
在C99中,truefalse是宏,您可以选择使用stdbool.h包含它们。在C99中,||的结果仍然是一个int类型。 - CB Bailey

5

使用您的宏:

#define SAFEMALLOC(SIZEOF) (malloc(SIZEOF) || (void*)(fprintf(stderr,"[%s:%d]Out of memory(%d bytes)\n",__FILE__,__LINE__,SIZEOF),exit(EXIT_FAILURE),0))

#include <stdio.h>
#include <stdlib.h>

int main(void)
{
    char *p = SAFEMALLOC(10);
    char *q = SAFEMALLOC(2000);

    printf("p = %p, q = %p\n", p, q);

    // Leak!
    return 0;
}

警告(应该是一个提示):

weird.c:8: warning: cast to pointer from integer of different size
weird.c:8: warning: initialization makes pointer from integer without a cast
weird.c:9: warning: cast to pointer from integer of different size
weird.c:9: warning: initialization makes pointer from integer without a cast

输出:

p = 0x1, q = 0x1

总之,不是很安全!编写一个函数可能会更少出错。

我会将其转换为(char*)。但现在我不明白为什么p和q返回0x1!那不是相同的地址/指针吗? :-) - Pierre
2
@Pierre:不,你不应该将其转换为char*;这样会隐藏告诉你有问题的警告! - CB Bailey
@Pierre “但是现在我不明白为什么p和q返回0x1!”--那是因为你甚至没有做最基本的工作去理解你正在编程的语言。(x || y)的值始终只能是0或1。 - Jim Balter
@Pierre 关于类型转换,优秀的程序员会像对待X光或抗生素一样...只在必要时使用。 - Jim Balter

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接