【发布时间】:2015-03-31 13:18:26
【问题描述】:
为了生成文件名,我需要为sprintf 提供一些缓冲内存。这些缓冲区的大小在过去是相当随意地选择的。这很容易在将来导致非常讨厌的堆栈溢出错误,例如int 变为 64 位长,但字符串缓冲区大小选择为 10 个字符,因为这是 32 位 int 可以容纳的最大位数。
一些 MWE:
for (int i = 0; i < mpi_size; i++) {
//magic number: 32bit integer has 10 digits,
//+6 for "/rank_", +1 for null termination
char path2[strlen(path) + 17];
//This can possibly be an access violation, or a very hard to
//find bug:
sprintf(path2, "%s/rank_%d", path, i);
//Using path2 to access some file
}
在其他地方选择的尺寸完全不同,人们非常确定int 不会大于例如3位数。这会更容易导致问题。
什么是完美且便携的解决方案?
我在 gnome 库中找到了函数 g_printf_string_upper_bound,它可以优雅可靠地解决这个问题。
在 C 标准、POSIX 或其他地方有类似的东西吗?
【问题讨论】:
-
snprintf 是 C99 的一部分。
-
当然,但是结果字符串会是错误的......
-
你必须检查返回值。如果是
size或更多,则输出被截断。 -
没错,输出字符串会被截断。这将使我摆脱堆栈损坏,但不会解决问题。