【发布时间】:2016-12-07 10:47:24
【问题描述】:
我正在将一个大型 c 项目从 Windows 移植到 Unix,源代码包含数千个对 logprint 函数的调用,声明如下:
VOID logprint(DWORD level, LPCSTR format, ...);
现在这是我的两个问题:
1.) 使用的格式类型说明符不可移植
代码将%lu 用于ULONG 变量。在 Windows 上这很好,因为 ULONG 是 unsigned long 的 typedef。但是,在移植代码时,我无法重现此 typedef,因为根据 [MS-DTYP],ULONG 必须始终是 32 位的(注意:对于 Microsoft 的 c 编译器,unsigned long 始终是 32 位)。
所以我创建了一个 Windows 类型头文件wtypes.h,它在stdint.h 和limits.h 的帮助下定义了基本的Windows 数据类型。
当然,如果系统 unsigned long 是 64 位而我的 ULONG 是 32 位,那么现在这会导致无效读取,因为 %lu 说明符。所以我还必须为所有ULONG logprint 参数添加一个(unsigned long) 强制转换。
ULONG 当然只是一个例子......
2.) 使用了无效的格式类型说明符
此外,该代码使用了大量无效的格式说明符。例如。 %d 用于 DWORD 参数。
当然很容易解决:
- 识别所有日志打印调用
- 确定每个参数的类型
- 验证是否使用了正确的格式说明符
- 为参数添加正确的类型转换
例子:
替换:
ULONG ulMin, ulMax;
...
logprint(FATAL, "specified interval is invalid %ld..%u out of range",
ulMin, ulMax);
与:
logprint(FATAL, "specified interval is invalid %lu..%lu",
(unsigned long) ulMin, (unsigned long) ulMax);
但这至少需要我两个星期,然后我的大脑就会乱码。
所以我的实际问题:
是否有任何自动化工具可以进行此类更改?
作为最低要求,该工具必须能够识别参数的类型并在它们前面加上类型转换。一旦有类型转换,我就可以轻松编写一个修复格式说明符的 python 脚本。
【问题讨论】:
-
调整格式优于强制转换,绝对!正如您所使用的那样,使用来自
inttypes.h的格式化宏。在 10 年左右将其移植到 64 位的人会因此而爱你。 ;-) -
这个
logprint(FATAL, "specified interval is invalid %ld..%u out of range", ulMin, ulMax);应该变成logprint(FATAL, "specified interval is invalid %"PRIu32"..%"PRIu32" out of range", ulMin, ulMax);。 -
为胜利创建
inttypes.h是在眨眼之间完成的,与其他人相比...... ;-) -
您可以定义自己的宏,例如“inttypes.h”中的 PRI 宏,但针对 Windows 类型进行了调整。例如。
#define PRI_ULONG "lu"用于 Windows,#define PRI_ULONG "u"用于 Unix。 -
您可以创建自己的标题
scnprtfmt.h(扫描、打印格式),并将其包含在您的代码中。带有inttypes.h的系统上的“实现”主要是#include <inttypes.h>;在没有本机inttypes.h的系统上,您提供等效的功能。这是可行的。主要工作是更改格式字符串本身以正确使用宏。