【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 风格格式检查 |

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

相关推荐
鱼很腾apoc8 小时前
【MySQL】第4期 用户管理与 C 语言连接编程详解
linux·服务器·c语言·mysql·connector/c
himobrinehacken10 小时前
位运算揭秘:左右移与符号位陷阱
c语言·c++·算法·安全
水饺编程13 小时前
第2章:Linux 基础,rm 命令
linux·c语言·汇编
夏虫不可与之言冰13 小时前
第三课 点亮 LED 与定时器非阻塞闪烁
c语言·c++·vscode·单片机·嵌入式硬件·物联网
JasmineX-114 小时前
数据结构(笔记)——顺序栈
c语言·数据结构·笔记
2401_8628808214 小时前
嵌入式Linux系统移植与驱动开发完整指南
linux·c语言·驱动开发
我叫洋洋15 小时前
Cadence 16.6 从 OrCAD Capture 原理图到 Allegro PCB 全流程(含 5 个常见坑)
c语言·eda·嘉立创
水饺编程16 小时前
第2章:Linux 基础,关机命令
linux·c语言·汇编
Brilliantwxx17 小时前
【Linux】IO(上)全篇:文件本质、C 接口、系统调用与文件描述符
linux·运维·服务器·c语言
坐看风云变幻18 小时前
《嵌入式工程师的软硬件修仙之路》第 2 期|C 语言筑基:指针与内存模型
c语言·开发语言