意外的 sscanf 结果
Unexpected sscanf Result
我有一个 sscanf
语句出现异常。这是循环 #8000 附近的某个地方,它突然这样做了。这是代码,其中 str
是从文件解析的字符串:
char a1[6], a2[6], op[6], a3[6];
int success = sscanf(str.c_str(),"%*s %s %*s %s %s %s",a1, a2, op, a3);
这是问题行上的 gdb 输出(str
是 "assign po012 = po011;"
):
(gdb) print str
= {<std::__1::__basic_string_common<true>> = {<No data fields>}, static __short_mask = 1, static __long_mask = 1,
__r_ = {<std::__1::__compressed_pair_elem<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >::__rep, 0, false>> = {__value_ = {{__l = {__cap_ = 97, __size_ = 23, __data_ = 0x1003001d0 " assign po012 = po011;"}, __s = {{
__size_ = 97 'a', __lx = 97 'a'},
__data_ = "[=11=]0[=11=]0[=11=]0[=11=]0[=11=]0[=11=]0[=11=]07[=11=]0[=11=]0[=11=]0[=11=]0[=11=]0[=11=]0[=11=]00[=11=]10[=11=]0[=11=]1[=11=]0[=11=]0"}, __r = {__words = {
97, 23,
4298113488}}}}}, <std::__1::__compressed_pair_elem<std::__1::allocator<char>, 1, true>> = {<std::__1::allocator<char>> = {<No data fields>}, <No data fields>}, <No data fields>}, static npos = 18446744073709551615}
(gdb) n
81 string A1(a1);
(gdb) print a1
= "[=11=]0o012"
(gdb) print a2
= "po011;"
a2
具有预期值,但在这种情况下 a1
发生了什么?
您的数组长度为六:
char a1[6], a2[6], op[6], a3[6];
然而,sscanf
导致 "po011;"
被写入 a2
,这需要 7 个 个字符,因为 sscanf
将添加空终止符。因此,sscanf
导致未定义的行为。
实际上,在您的实现中,空终止符被添加到 a1
的开头,它从预期的 "po012"
更改为 "[=18=]0o012"
(最初的 p
覆盖)。看起来您的实现选择在 a2
之后立即存储 a1
,因此溢出的 a2
覆盖了 a1
。这是触发未定义行为时可能发生的事情之一。
我有一个 sscanf
语句出现异常。这是循环 #8000 附近的某个地方,它突然这样做了。这是代码,其中 str
是从文件解析的字符串:
char a1[6], a2[6], op[6], a3[6];
int success = sscanf(str.c_str(),"%*s %s %*s %s %s %s",a1, a2, op, a3);
这是问题行上的 gdb 输出(str
是 "assign po012 = po011;"
):
(gdb) print str
= {<std::__1::__basic_string_common<true>> = {<No data fields>}, static __short_mask = 1, static __long_mask = 1,
__r_ = {<std::__1::__compressed_pair_elem<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >::__rep, 0, false>> = {__value_ = {{__l = {__cap_ = 97, __size_ = 23, __data_ = 0x1003001d0 " assign po012 = po011;"}, __s = {{
__size_ = 97 'a', __lx = 97 'a'},
__data_ = "[=11=]0[=11=]0[=11=]0[=11=]0[=11=]0[=11=]0[=11=]07[=11=]0[=11=]0[=11=]0[=11=]0[=11=]0[=11=]0[=11=]00[=11=]10[=11=]0[=11=]1[=11=]0[=11=]0"}, __r = {__words = {
97, 23,
4298113488}}}}}, <std::__1::__compressed_pair_elem<std::__1::allocator<char>, 1, true>> = {<std::__1::allocator<char>> = {<No data fields>}, <No data fields>}, <No data fields>}, static npos = 18446744073709551615}
(gdb) n
81 string A1(a1);
(gdb) print a1
= "[=11=]0o012"
(gdb) print a2
= "po011;"
a2
具有预期值,但在这种情况下 a1
发生了什么?
您的数组长度为六:
char a1[6], a2[6], op[6], a3[6];
然而,sscanf
导致 "po011;"
被写入 a2
,这需要 7 个 个字符,因为 sscanf
将添加空终止符。因此,sscanf
导致未定义的行为。
实际上,在您的实现中,空终止符被添加到 a1
的开头,它从预期的 "po012"
更改为 "[=18=]0o012"
(最初的 p
覆盖)。看起来您的实现选择在 a2
之后立即存储 a1
,因此溢出的 a2
覆盖了 a1
。这是触发未定义行为时可能发生的事情之一。