_attribute_((format(printf, 2, 3))) 变参函数的格式检查

 

https://gcc.gnu.org/onlinedocs/gcc-4.8.5/gcc/Function-Attributes.html

 

format (archetypestring-indexfirst-to-check)The format attribute specifies that a function takes printfscanfstrftime or strfmon style arguments that should be type-checked against a format string. For example, the declaration:

          extern int
          my_printf (void *my_object, const char *my_format, ...)
                __attribute__ ((format (printf, 2, 3)));

causes the compiler to check the arguments in calls to my_printf for consistency with the printf style format string argument my_format.

The parameter archetype determines how the format string is interpreted, and should be printfscanfstrftimegnu_printfgnu_scanfgnu_strftime or strfmon. (You can also use __printf____scanf____strftime__ or __strfmon__.) On MinGW targets, ms_printfms_scanf, and ms_strftime are also present. archetype values such as printf refer to the formats accepted by the system's C runtime library, while values prefixed with ‘gnu_’ always refer to the formats accepted by the GNU C Library. On Microsoft Windows targets, values prefixed with ‘ms_’ refer to the formats accepted by the msvcrt.dll library. The parameter string-index specifies which argument is the format string argument (starting from 1), while first-to-check is the number of the first argument to check against the format string. For functions where the arguments are not available to be checked (such as vprintf), specify the third parameter as zero. In this case the compiler only checks the format string for consistency. For strftime formats, the third parameter is required to be zero. Since non-static C++ methods have an implicit this argument, the arguments of such methods should be counted from two, not one, when giving values for string-index and first-to-check.

In the example above, the format string (my_format) is the second argument of the function my_print, and the arguments to check start with the third argument, so the correct parameters for the format attribute are 2 and 3.

The format attribute allows you to identify your own functions that take format strings as arguments, so that GCC can check the calls to these functions for errors. The compiler always (unless -ffreestanding or -fno-builtin is used) checks formats for the standard library functions printffprintfsprintfscanffscanfsscanfstrftimevprintfvfprintf and vsprintf whenever such warnings are requested (using -Wformat), so there is no need to modify the header file stdio.h. In C99 mode, the functions snprintfvsnprintfvscanfvfscanf and vsscanf are also checked. Except in strictly conforming C standard modes, the X/Open function strfmon is also checked as are printf_unlocked and fprintf_unlocked. See Options Controlling C Dialect.

For Objective-C dialects, NSString (or __NSString__) is recognized in the same context. Declarations including these format attributes are parsed for correct syntax, however the result of checking of such format strings is not yet defined, and is not carried out by this version of the compiler.

The target may also provide additional types of format checks. See Format Checks Specific to Particular Target Machines.

 

 

变参函数的格式检查

 

GNU 通过 __atttribute__ 扩展的 format 属性,用来指定变参函数的参数格式检查。

它的使用方法如下:

  1. __attribute__(( format (archetype, string-index, first-to-check)))
  2. void LOG(const char *fmt, ...) __attribute__((format(printf,1,2)));

我们经常实现一些自己的打印调试函数。这些打印函数往往是变参函数,那编译器编译程序时,怎么知道我们的参数格式对不对呢?因为我们实现的是变参函数,参数的个数和格式都不确定。所以编译器表示压力很大,不知道该如何处理。

办法总是有的。这不,__atttribute__ 的format属性这时候就自带 BGM,隆重出场了。如上面的示例代码,我们定义一个 LOG 变参函数,用来实现打印功能。那编译器编译程序时,如何检查我们参数的格式是否正确呢?其实很简单,通过给 LOG 函数添加 __atttribute__ ((format(printf,1,2))) 这个属性声明,就是告诉编译器:你知道printf函数不?你怎么对这个函数参数格式检查的,就按同样的方法,对 LOG 函数进行检查。

属性 format(printf,1,2) 有三个参数。第一个参数 printf 是告诉编译器,按照 printf 函数的检查标准来检查;第2个参数表示在 LOG 函数所有的参数列表中,格式字符串的位置索引;第3个参数是告诉编译器要检查的参数的起始位置。

posted @ 2023-03-20 17:42  sinferwu  阅读(322)  评论(0编辑  收藏  举报