C中的nonnull参数与NULL比较

4
在下面的函数中,旨在释放分配给类型为 Maze 的指针的一些内存,其中 Maze 是我在另一个文件中定义的结构体。

我得到了编译器错误nonnull argument 'maze' compared to NULL 这只是一个警告,但我必须保留打开警告。

以下是该函数的代码:

void free_maze(Maze *maze) {
    if (maze == NULL) {
        return;
    }

    free(maze);
    return;
}

据我理解,这是检查指向结构体的指针是否为NULL的正确方法。但是我在这里做错了什么吗?


4
你的函数是否被另一个带有“nonnull”指令的函数调用?另外,即使'maze'为NULL,你也可以安全地使用free释放它。 - Jean-François Fabre
5
free(NULL)没有效果。由于仅仅代码本身并不会发出任何警告, 因此我们需要一个[mcve]。 - Jean-François Fabre
2
{btsdaf} - dbush
3
请参考这篇相关讨论:这种 C 语言释放内存的方式是否可行?。“担心的是可能已经调用了它”,但是你的 free_maze 函数并没有解决这个问题。它只是检查了 maze 是否为空,并且 free(NULL); 完全没有问题。 - P.P
2
{btsdaf} - ikegami
显示剩余16条评论
1个回答

11

警告的原因可能是因为free_maze的声明与以下代码相似:

extern void free_maze (Maze *maze)
        __attribute__((nonnull));

__attribute__((nonnull));是GCC特有的扩展。

因此,该声明表示free_maze不应传递NULL。编译器将尝试检测此约束的违规情况并发出警告。由于您不应该传递NULL,因此检查它几乎没有意义。

即使没有属性,您也不需要检查,因为free(NULL)是安全的。

关于您的编辑: 一次调用

free(maze);

在调用方的作用域中不会更改maze。如果您无意中再次使用相同的指针调用free,则第二次调用将不会使用NULL,而是使用一个悬空指针,导致未定义的行为。请不要重复释放。


{btsdaf} - Colin Harrison
{btsdaf} - Colin Harrison
1
我有同样的问题,而且在我看来这些警告是无意义的。attribute((nonnull)); 是为了避免错误使用。编译器可以检测到硬编码的NULL值并发出警告,但不能保证在运行时参数永远不会为NULL。因此,在解引用指针之前检查指针参数以获得健壮的代码非常重要。因此,对与NULL进行比较发出警告就毫无意义了。因此,我认为唯一的方法是使用-Wno-nonnull-compare禁用此警告。 - Hans Dampf
@HansDampf 编译器还可以根据某些函数参数不会为空的知识进行优化。 编译器将属性解释为程序员对参数永远不会为空的承诺。如果您正在检查空值,则不信任自己的承诺。这是非常不好的。 - n. m.

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