Gio*_*ino 3 c printf network-programming clang
我有这一大块代码
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;
}
Run Code Online (Sandbox Code Playgroud)
当我编译它(Clang 5.0.0 with -Weverything)时,我获得了这些警告:
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)
^
Run Code Online (Sandbox Code Playgroud)
同样的事情发生在另一个函数vsnprintf(buf,sizeof(buf),fmt,ap);
我该如何解决此警告?
谢谢
显然,解决方案是告诉Clang你vsnprintf是在一个函数中调用的,它通过调用来实现printf函数族的行为vsnprintf.您可以使用属性执行此操作,如下所述:
__attribute__((__format__ (__printf__, 3, 0)))
static void err_doit(int errnoflag, int level, const char *fmt, va_list ap)
{
...
}
Run Code Online (Sandbox Code Playgroud)
这将检查格式字符串是否是调用函数的文字.作为err_doit已经采取va_list,应指定在调用它的职能的格式了.第二个数字,这里为0,应该是可变参数的参数索引,....另见本讨论.
函数属性是gcc的非标准扩展,也是为Clang实现的.如果要保持代码编译器独立,则应将属性包装在宏中,以便为不知道属性的编译器隐藏它.
(免责声明:我无法用Clang检查这个,但它适用于gcc.编辑:修复了错误的参数索引)