如何通过GCC检测vsnprintf中的隐式转换

时间:2015-05-22 09:55:37

标签: c++ gcc g++ printf

我希望g ++在vsnprintf中检测下面不正确的隐式转换。 我试着用:

g++ -Wall -Werror -Wconversion -Wformat  test.cpp -o test.ext

但没有警告。代码如下:

#include <cstdio>
#include <cstdarg>


void PrintFError ( const char * format, ... )
{
  char buffer[256];
  va_list args;
  va_start (args, format);
  vsnprintf (buffer,256,format, args);
  perror (buffer);
  va_end (args);
}


enum LEVEL
 {
     INFO = 1,
     WRN = 2
 };

int main ()
{

  PrintFError ("Error opening %s", WRN); // WRN is enum not char*, expecte some compile warning here

  return 0;
}

3 个答案:

答案 0 :(得分:4)

您必须在函数中添加属性以允许gcc检查:

void PrintFError ( const char * format, ... ) __attribute__ ((format (printf, 1, 2)))

现在最好使用可变参数模板。

之类的东西
template <typename ...Ts>
void PrintFError (const char * format, Ts&&...args)
{
    char buffer[256];
    vsnprintf (buffer, 256, format, std::forward<Ts>(args)...);
    perror (buffer);
}

答案 1 :(得分:1)

当您将参数传递给...而不是printf内时,此类转化发生在调用网站上。

有关详细信息,请参阅Variadic arguments

枚举器转换为int。但是,C ++ 11范围的枚举器不会被隐式转换。

答案 2 :(得分:1)

如果您使用的是GCCClang,则可以利用他们的function attributes功能,并宣布您的打印功能

void PrintFError ( const char * format, ...) 
   __attribute__(format(printf(1,2)));

然后, direct 使用该函数可能会触发警告。

顺便说一句,你也可以自定义你最近的g++(或gcc,如果用C编码)编译器,可以使用MELT进行扩展。然后,您可以定义自己的函数属性,并添加自己的检查优化过程。除非你对GCC内部非常熟悉,否则这将需要你至少一周的工作。

最后,在C ++(不在C语言中)中,您可以定义自己的输出operator <<函数,也许还有一个宏

 #define MY_ERROR_AT(Fil,Lin,Out) do { \ 
   std::cerr << Fil << ":" << Lin << ": " << Out << std::endl; } \
   while(0) 
 #define MY_ERROR(Out) MY_ERROR_AT(__FILE__,__LINE__,Out)

和代码MY_ERROR("x=" << x)稍后在你的程序中。

顺便说一下,你也可以使用C ++ variadic templates,但是你应该使用符合C ++ 11或C ++ 14的编译器(例如g++ -std=c++14)。