这是我的警告.
Missing sentinel in function call
Run Code Online (Sandbox Code Playgroud)
我怎么能删除它.
我正在使用linux和gcc编译器.
Mic*_*ord 64
看起来您可能没有终止数组声明NULL
.如果没有null,你可能会有一些内存怪异,因为运行时不知道数组的结束位置和下一位内存的开始.
Pet*_*all 47
我刚遇到同样的问题.导致它的代码是......
execl("/bin/bash", "/bin/bash", fname, '\0');
Run Code Online (Sandbox Code Playgroud)
但它应该......
execl("/bin/bash", "/bin/bash", fname, (char *)0);
Run Code Online (Sandbox Code Playgroud)
第一个版本的问题是参数列表意味着以空指针结束.但'\ 0'不是空指针,而是空字符.所以值(0)是正确的,它只是类型错误.
(char*)0也是零,但是作为char 指针强制转换,它是一个空指针(即它指向地址0).这是必需的,因此系统可以告诉参数列表的结束位置,以便在最后一个参数列表之后不会继续扫描参数.这样做会得到无效的指针,可能指向任何内存 - 这可能会导致分段错误.
那个(char*)0被称为sentinel,它是第一个例子中缺少的东西.
最后请注意,NULL定义为(void*)0,所以
execl("/bin/bash", "/bin/bash", fname, NULL);
Run Code Online (Sandbox Code Playgroud)
同样有效,而且更方便一点.(感谢@mah).
小智 18
在Xcode中,如果使用objective-c进行编码,并且使用的是一些采用变量参数列表的方法,则需要在列表末尾添加nil对象.
例如:
N SArray*names = [NSArray arrayWithObjects:@"Name1",@"Name2"]; //将导致上述警告
但是, NSArray*names = [NSArray arrayWithObjects:@"Name1",@"Name2",nil]; //正确
希望这会有所帮助!
Cir*_*四事件 11
使用(void*)0
或(void *)NULL
代替NULL
警告sentinel
由Jichao提到的function属性生成.记录于:https://gcc.gnu.org/onlinedocs/gcc-5.1.0/gcc/Function-Attributes.html#index-g_t_0040code_007bsentinel_007d-function-attribute-3226其中说:
对于任何指针类型,此上下文中的有效NULL定义为零.如果您的系统使用整数类型定义NULL宏,则需要添加显式强制转换.GCC用一个适当重新定义NULL的副本替换stddef.h.
在ANSI C中,NULL可以是0
或者(void *)0
,但只有指针满足此属性,另请参见:NULL,'\ 0'和0之间有什么区别
虽然0
将使用常规指针参数转换为空指针,但是不可能将零指针的零整数与vararg区分开来,因此差异至关重要.请参阅:指针的默认参数提升
是的,GCC保证NULL为指针,因为NULL由GCC提供stddef.h
(某些ANSI C头在GCC中,其他在glibc中),我不确定这是否可能被破坏,因为它sentinel
是一个GCC扩展开始.
但我仍然会写(void *)NULL
或(void*)0
只是为了确定.
此外,POSIX和execl()函数终止都man execl
需要"空指针",这是Sentinel使用的典型示例.
NULL
不能保证在那里工作,因为它是一个"空指针常量",它不一定是"空指针",因此通过使用(void *)0
到处都可以使您熟悉已知的API.另请参见:((void*)0)空指针常量?|| (int*)0是否为空指针?
GCC 5.2.0 execl
以内置方式提供并以sentinel
编程方式设置:
DEF_EXT_LIB_BUILTIN (BUILT_IN_EXECL, "execl", BT_FN_INT_CONST_STRING_CONST_STRING_VAR, ATTR_SENTINEL_NOTHROW_LIST)
Run Code Online (Sandbox Code Playgroud)
还有一个glibc 2.21版本execl
没有该属性.
一个简单的例子:
#include <stdio.h>
#include <stdarg.h>
void print_strings(const char* first, ...) __attribute__((sentinel));
void print_strings(const char* first, ...)
{
va_list ap;
const char* tmp;
if (!first)
return ;
printf("%s\n", first);
va_start(ap, first);
while (1) {
tmp = va_arg(ap, const char*);
if (tmp == 0)
break;
printf("%s\n", tmp);
};
va_end(ap);
}
int main()
{
print_strings("how are you?", "i'm fine", "and you?", NULL);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
在 main 中,如果你调用 print_strings asprint_strings("how are you?", "I'm fine", "and you?")
没有结尾NULL
,GCC 会抱怨“缺少哨兵”。
因为我们在函数中添加了哨兵函数属性print_strings
。它是一个 gcc 扩展,用于指定变量参数应以 NULL 结尾。因此,如果您不以 NULL 结束变量参数,编译器可以检测到它并显示警告。