我有一个接口,其中一些函数是用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++相关问答推荐

segfault在C中使用getline()函数

C中空终止符后面的数字?

GCC不警告隐式指针到整数转换'

在32位处理器上优化53—32位模计算>

如果实际的syscall是CLONE(),那么为什么strace接受fork()呢?

难以理解Makefile隐含规则

无效指针值在函数调用之间莫名其妙地改变

初始变量重置后,char[]的赋值将消失

Square不与Raylib一起移动

getline()从c中的外部函数传递指针时输出null

链接器脚本和C程序使用相同的头文件,这可能吗?

条件跳转或移动取决于未初始化值(S)/未初始化值由堆分配创建(Realloc)

不确定如何处理此编译错误

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

DennisM.Ritchie的C编程语言一书中关于二进制搜索的代码出现错误?

C循环条件内的函数

C struct 中的冒泡排序

函数指针作为函数参数 - 应该使用 const 吗?

将数组中的所有元素初始化为 struct 中的相同值

比 * 更快的乘法