Clang 5.0上的vsprintf和vsnprintf 警告

我有这一大块代码

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)时,我获得了这些警告:

 Building C object lib/netutils/CMakeFiles/netutils.dir/error.co /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)也会发生同样的事情;

我该如何解决此警告?

谢谢

显然,解决方案是告诉Clang你的vsnprintf是在一个函数中调用的,它通过调用vsnprintf来实现printf系列函数的行为。 您可以使用属性执行此操作, 如下所述 :

 __attribute__((__format__ (__printf__, 3, 0))) static void err_doit(int errnoflag, int level, const char *fmt, va_list ap) { ... } 

这将检查格式字符串是否是调用函数的文字。 由于err_doit已经采用了va_list ,因此您应该在调用它的函数上指定格式。 第二个数字,这里为0,应该是可变参数的参数索引, ... 另见本讨论 。

函数属性是gcc的非标准扩展,也是为Clang实现的。 如果要保持代码编译器独立,则应将属性包装在宏中,以便为不知道属性的编译器隐藏它。

(免责声明:我无法用Clang检查这个,但它适用于gcc。编辑:在示例中修复了错误的参数索引)