我尝试了你的代码,并且还看到了第二个代码的段错误strcat()
。我找到command[250]
之后立即分配whitespaceseparator[2]
在我系统的堆栈上:
(gdb) p &whitespaceseparator
$1 = (char (*)[2]) 0xbf90acd4
(gdb) p &command
$2 = (char (*)[250]) 0xbf90acd6
例如(这里command
begins "foo..."
),事情是这样安排的:
whitespaceseparator
|
| command
| |
v v
+---+---+---+---+---+---+---+---+
|' '| 0 |'f'|'o'|'o'|'.'|'.'|'.'| ...
+---+---+---+---+---+---+---+---+
我不能保证您的系统上会发生同样的情况(即使在同一编译器的不同版本之间,堆栈上的本地布局也可能有所不同),但似乎有可能。在我的身上,发生的情况如下:
正如其他人所说,strcat()
将第二个字符串附加到第一个字符串(结果将等于第一个参数)。所以,第一个strcat()
溢出whitespaceseparator[]
(并返回whitespaceseparator
as whitespace_and_pid
):
+---+---+---+---+---+---+---+---+
|' '|'1'|'2'|'3'|'4'| 0 |'.'|'.'| ...
+---+---+---+---+---+---+---+---+
第二strcat()
尝试追加whitespace_and_pid
(== whitespaceseparator
) 到字符串command
。副本的第一个字符将覆盖字符串的终止 0command
:
| ===copy===> |
v v
+---+---+---+---+---+---+---+---+
|' '|'1'|'2'|'3'|'4'|' '|'.'|'.'| ...
+---+---+---+---+---+---+---+---+
副本继续……
| ===copy===> |
v v
+---+---+---+---+---+---+---+---+
|' '|'1'|'2'|'3'|'4'|' '|'1'|'.'| ...
+---+---+---+---+---+---+---+---+
| ===copy===> |
v v
+---+---+---+---+---+---+---+---+
|' '|'1'|'2'|'3'|'4'|' '|'1'|'2'| ...
+---+---+---+---+---+---+---+---+
并将继续复制" 1234 1234 1234"
...直到它脱离进程地址空间的末尾,此时您会遇到段错误。