【C】利用GCC扩展属性进行格式化字符串的静态检查

一、问题引入

在项目实践中,时常发生自定义的格式化输入输出函数中,因为打印格式与参数类型不匹配导致的故障。典型的问题有:

  • 格式化输出使用%s打印一个整型,导致进程跑飞
  • 格式化输出使用%d打印一个长整型,导致打印数据截断
  • 格式化输出格式符多于实际参数个数,导致进程跑飞
  • 格式化输入使用%u打印一个 unsigned char 或 unsigned short 类型整型,导致踩内存

下面,借助 GCC 编译器的__attribute__((format(...))) 扩展属性,用于在编译时进行格式字符串的静态检查,提前发现问题。

示例

cpp 复制代码
int ios_snprintf_s(char * restrict s, rsize_t n, const char *restrict format, ...) __attribute__((format(printf, 3, 4)))

二、示例详解

1. 格式字符串检查

  • format: 指定这是一个格式字符串函数
  • printf: 指定使用 printf 系列的格式规则进行检查
  • 3, 4: 指定参数位置
  • 第3个参数是格式字符串位置 (即const char *restrict format)
  • 第4个参数是可变参数列表的开始位置 (...)

2. 编译时检查

编译器会在编译时检查:

cpp 复制代码
// 示例用法
char buf[100];
ios_snprintf_s(buf, sizeof(buf), "Name: %s, Age: %d", name, age);

// 如果格式字符串与参数不匹配,编译时会报警告
ios_snprintf_s(buf, sizeof(buf), "Name: %s, Age: %d", name); 
// 警告:参数数量不足
  1. 实际效果
cpp 复制代码
// 正确的使用 - 无警告
ios_snprintf_s(buffer, size, "Hello %s!", name);

// 错误的使用 - 编译警告
ios_snprintf_s(buffer, size, "Hello %s!", 123);
// 警告:格式 '%s' 需要 'char*' 但参数是 'int'

ios_snprintf_s(buffer, size, "Value: %d");
// 警告:格式 '%d' 缺少对应参数

三、类似属性

|------------------------|-----------------|
| 属性 | 用途 |
| format(printf, n, m) | printf 风格格式检查 |
| format(scanf, n, m) | scanf 风格格式检查 |
| format(strftime, n, m) | strftime 风格格式检查 |

这种属性在项目安全编码中特别有用,可以提前发现格式化字符串相关的潜在错误。

相关推荐
RuoZoe1 天前
重塑WPF辉煌?基于DirectX 12的现代.NET UI框架Jalium
c语言
祈安_4 天前
C语言内存函数
c语言·后端
norlan_jame6 天前
C-PHY与D-PHY差异
c语言·开发语言
czy87874756 天前
除了结构体之外,C语言中还有哪些其他方式可以模拟C++的面向对象编程特性
c语言
m0_531237176 天前
C语言-数组练习进阶
c语言·开发语言·算法
Z9fish6 天前
sse哈工大C语言编程练习23
c语言·数据结构·算法
代码无bug抓狂人6 天前
C语言之单词方阵——深搜(很好的深搜例题)
c语言·开发语言·算法·深度优先
CodeJourney_J6 天前
从“Hello World“ 开始 C++
c语言·c++·学习
枫叶丹46 天前
【Qt开发】Qt界面优化(七)-> Qt样式表(QSS) 样式属性
c语言·开发语言·c++·qt
with-the-flow6 天前
从数学底层的底层原理来讲 random 的函数是怎么实现的
c语言·python·算法