我有一个接口,其中一些函数是用nonnull GCC函数属性声明的,例如:

// declaration in .h
__attribute__((nonnull))
int foo(const char *bar);
[...]
// definition in .c
int foo(const char *bar) {
    if (bar == NULL)
        return -1;

    // do something with bar
    ...
}

但零判断触发了-Wnonnull-compare%GCC的警告. 问题是nonnull属性的文档说明它:

使编译器在调用[...]时判断参数[...]都是非空的.

问题是,它没有说明任何有关运行时的内容.因此,如果我为了取悦GCC而删除此复选框,我可能会隐藏或在必要时检测到调用程序中的错误.

那么,在这种情况下,这一警告应该沉默吗?或者,文档中是否存在某种错误,使得代码没有经过判断,实际上是正确的?

FTR,我的编译器版本是11.4.0.

推荐答案

-Wnonnull-Compare警告是不是具有误导性?

不是的.在the GCC 11.4 documentation中有一个错误.它给出了nonnull属性的一个例子,其中说:

例如,声明…使编译器在对my_memcpy的调用中判断参数destsrc是否是非空的.

然而,该属性的非示例描述性文本表达了一些不同的东西(强调添加了):

它表示引用的参数为must be个非空指针.

这一点在the GCC 12.3 documentation中得到更正,其中关于该示例的文本被更改为:

例如,声明…通知编译器,在对my_memcpy的调用中,参数destsrc为非空.

而非例证的描述性文本保持不变.

因此,nonnull属性是对编译器的一个断言,它可以假设指针不为null,因此将非null指针与null进行比较的警告是正确的.

总而言之,当为不应该为空的参数传递空指针时,nonnull属性不提供您想要的报告功能.

C++相关问答推荐

正在try 将文件/文件夹名从目录 struct 存储到链接列表

以下声明和定义之间的区别

预先分配虚拟地址空间的区域

为什么我的Hello World EFI程序构建不正确?

用C语言计算文本文件中的整数个数

是否需要包括<;errno.h>;才能使用perror?

关于";*(++p)->;t";、&++p->;t";和&q;++*p->;t";的问题

C I/O:在Windows控制台上处理键盘输入

如何在GDB中查看MUSL的源代码

使用nmake for程序比Hello World稍微复杂一些

运行时错误:在索引数组时加载类型为';char';`的空指针

当用C打印过多的';\n';时输出不正确

Linux/C:带有子进程的进程在添加waitid后都挂起

OMP并行嵌套循环

System V 消息队列由于某种原因定期重置

如何向 execl 创建的后台程序提供输入?

在 atmega4809 上使用 UART1 发送多个字符会导致发送 0xFF

在C中打印带有UTF8字符的字符串

关于使用堆栈将递归转换为迭代的困惑

可以从 C 调用 f77 子 routine 吗?