如何让GCC检查类printf函数的参数

来篇又短又水的。

大家都知道在c语言中有一类可变参数(variable-argument)的函数,像printf、scanf,这类函数的一大优势是输入参数的数量和类型都可以自由控制,但是问题也很明显,如果可变参数输入的个数或者类型不对,正常情况下编译器检查不出这样的错误,而实际运行却可能破坏堆栈,导致一些古怪的运行结果,很难定位到问题。

 

gcc中使用__attribute__format 可以解决这个问题。该__attribute__属性可以给被声明的函数加上类似printf或者scanf的特征,从而使编译器检查函数声明和函数实际调用参数之间的格式化字符串是否匹配。该功能十分有用,尤其是处理一些很难发现的bug。

format的语法格式为:

format (archetype, string-index, first-to-check)

format属性告诉编译器,按照printf, scanf,

strftime或strfmon的参数表格式规则对该函数的参数进行检查。“archetype”指定是哪种风格;“string-index”指定传入函数的第几个参数是格式化字符串;“first-to-check”指定从函数的第几个参数开始按上述规则进行检查。

具体使用格式如下:

__attribute__((format(printf,m,n)))

__attribute__((format(scanf,m,n)))

其中参数m与n的含义为:

m:第几个参数为格式化字符串(format string);

n:参数集合中的第一个,即参数“…”里的第一个参数在函数参数总数排在第几,注意,如果是在类成员函数中使用,还要考虑到隐藏的this指针。

 

举个例子:

1:

2:extern void myprint(const char *format,…)

__attribute__((format(printf,1,2)));

3:

4:void test()

5:{

6:     myprint(“i=%d\n”,6);

7:     myprint(“i=%s\n”,6);

8:     myprint(“i=%s\n”,”abc”);

9:     myprint(“%s,%d,%d\n”,1,2);

10:}

 

运行$gcc –Wall –c attribute.c attribute后,输出结果为:

 

attribute.c: In function `test’:

attribute.c:7: warning: format argument is not a pointer (arg 2)

attribute.c:9: warning: format argument is not a pointer (arg 2)

attribute.c:9: warning: too few arguments for format

 

如果不加__attribute__则不会有后面的warning。__attribute__还有许多其它的属性,具体看以参看百度文库

This entry was posted in linux and tagged , , , , . Bookmark the permalink.

Leave a Reply

Your email address will not be published. Required fields are marked *