这是
Can I answer my own question?
。欢迎提供更多答案。
如何检测
snprintf
C中的错误?
简短回答
回忆起
snprintf()
返回一个
int
.
使用更广泛的
size_t
或
unsigned
铸造
if ((size_t) snprintf(... ) >= sizeof buf) {
error();
}
或者迂腐地
int length_needed = snprintf(... );
if (length_needed < 0 || (unsigned) length_needed >= sizeof buf) {
error();
}
截断测试
有时的确如此
非常重要
从中检测截断的字符串
snprintf()
.
char buf[13];
char *command = "format_drive";
char *sub_command = "cancel";
snprintf(buf, sizeof buf, "%s %s", command, sub_command);
system(buf); // system("format_drive") leads to bye-bye data
OK代码
如果返回值满足或超过目标数组的大小,则执行一次测试
几乎
足够的
char buf[20];
if (snprintf(buf, sizeof buf, "Random int %d", rand()) >= sizeof buf) {
fprintf(stderr, "Buffer too small");
exit(EXIT_FAILURE);
}
负值
这个
snprintf
函数返回如果
n
足够大,不计算终止的空字符,或者如果发生编码错误,则为负值。因此,当且仅当返回值为非负且小于
N
.C11dr§7.21.6.5 3
健壮的代码会直接检查罕见的错误是否为负值
编码错误
.
if (some_int <= some_size_t)
不幸的是,这还不够
智力
将被转换为
尺寸
一
智力
然后,负返回值变为大的正返回值
尺寸
这
通常
远大于数组的大小,但尚未指定该大小。
// Pedantic check for negative values
int length_needed = snprintf(... as above ...);
if (length_needed < 0 || length_needed >= sizeof buf) {
fprintf(stderr, "Buffer too small (or encoding error)");
exit(EXIT_FAILURE);
}
错配征
一些编译器警告抱怨比较不同符号的整数,比如gcc
-Wsign-compare
具有
智力
和
尺寸
.投给
尺寸
看起来很合理。
警告:有符号和无符号整数表达式之间的比较[-Wsign compare]
// Quiet different sign-ness warnings
int length_needed = snprintf(... as above ...);
if (length_needed < 0 || (size_t) length_needed >= sizeof buf) {
fprintf(stderr, "Buffer too small (or encoding error)");
exit(EXIT_FAILURE);
}
迂腐的
C没有规定
智力
是
尺寸
.
尺寸
可以是
unsigned short
然后
SIZE_MAX < INT_MAX
(据我所知,没有这样的实施。)这是一个演员
(size_t) some_int
可能会改变价值。相反,将正回报值转换为
未签名
(
INT_MAX <= UINT_MAX
始终为true)将不会更改该值,并将确保使用之间最宽的无符号类型进行比较
unsigned
和
尺寸
.
// Quiet different sign-ness warnings
int length_needed = snprintf(... as above ...);
if (length_needed < 0 || (unsigned) length_needed >= sizeof buf) {
fprintf(stderr, "Buffer too small (or encoding error)");
exit(EXIT_FAILURE);
}