问题描述
我有这块代码
static void err_doit(int errnoflag, int level, const char *fmt, va_list ap)
{
int errno_save;
unsigned long n;
char buf[MAXLINE];
errno_save = errno;
#ifdef HAVE_VSNPRINTF
vsnprintf(buf, sizeof(buf), fmt, ap); /* this is safe */
#else
vsprintf(buf ,fmt, ap); /* this is not safe */
#endif
n = strlen(buf);
if (errnoflag)
snprintf(buf + n, sizeof(buf) - n, ": %s", strerror(errno_save));
strcat(buf, "\n");
if (daemon_proc) {
syslog(level,"%s", buf);
} else {
fflush(stdout);
fputs(buf, stderr);
fflush(stderr);
}
return;
}
当我编译它(Clang 5.0.0 with -Weverything)警告:
when i compile it (Clang 5.0.0 with -Weverything) i obtain those warnings:
Building C object lib/netutils/CMakeFiles/netutils.dir/error.c.o
/Users/User/Desktop/project.cmake/lib/netutils/error.c:98:16: warning: format string is not a string literal [-Wformat-nonliteral]
vsprintf(buf ,fmt, ap); /* this is not safe */
^~~
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.9.sdk/usr/include/secure/_stdio.h:66:57: note: expanded from
macro 'vsprintf'__builtin___vsprintf_chk (str, 0, __darwin_obsz(str), format, ap)
^
同样的事情发生在这个其他函数vsnprintf(buf,sizeof(buf),fmt,ap);
the same thing happens with this other function vsnprintf(buf, sizeof(buf), fmt, ap);
如何解决此警告?
感谢
推荐答案
显然,解决方案是告诉Clang vsnprintf
在实现 printf
函数的行为的函数内调用, $ c> vsnprintf 。您可以使用属性)执行此操作:
Apparently the solution is to tell Clang that your vsnprintf
is called within a function that implements the behaviour of the printf
family of functions by, well, calling vsnprintf
. You do this with an attribute, as described here:
__attribute__((__format__ (__printf__, 3, 0)))
static void err_doit(int errnoflag, int level, const char *fmt, va_list ap)
{
...
}
格式字符串是否为调用函数上的文字。因为 err_doit
已经有一个 va_list
,你应该指定调用它的函数的格式。第二个数字,这里是0,应该是可变参数 ...
的参数索引。请参见。
This checks whether the format string is a literal on the calling function. As err_doit
takes already a va_list
, you should specify the format on the functions that call it, too. The second number, which is 0 here, should then be the argument index of the variadic argument, ...
. See also this discussion.
函数属性是gcc的非标准扩展,也是为Clang实现的。如果你想保持代码编译器的独立性,你应该将属性包装在一个宏中,隐藏它为不知道属性的编译器。
Function attributes are a non-standard extension of gcc, which is also implemented for Clang. If you want to keep the code compiler independent, you should wrap the attributes in a macro that hides it for compilers that don't know attributes.
(免责声明:I couldn 'cl检查这个,但它适用于gcc。编辑:修正错误参数索引在例子中)
(Disclaimer: I couldn't check this with Clang, but it works for gcc. fixed wrong argument index in example)
这篇关于vsprintf和vsnprintf [-Wformat-nonliteral]警告的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!