当运行以下故意堆栈粉碎代码时,strcat会将源的值复制十次。
#include <stdio.h>
#include <stdlib.h>
int main() {
char a[16];
char b[16];
char c[32];
strcpy(a, "abcdefghijklmnop");
printf("a = %s\nb = %s\nc = %s\n\n", a, b, c);
strcpy(b, "ABCDEFGHIJKLMNOP");
printf("a = %s\nb = %s\nc = %s\n\n", a, b, c);
strcpy(c, b);
printf("a = %s\nb = %s\nc = %s\n\n", a, b, c);
strcat(c, b);
printf("a = %s\nb = %s\nc = %s\n\n", a, b, c);
return 0;
}
输出:
a = abcdefghijklmnop b = c =
a = abcdefghijklmnopABCDEFGHIJKLMNOP b = ABCDEFGHIJKLMNOP c =
a = abcdefghijklmnopABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP b = ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP c = ABCDEFGHIJKLMNOP
a = abcdefghijklmnopABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP b = ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP c = ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP
**堆栈粉碎检测到 * :./ sctrcpytest终止
构建参数:
gcc -O0 -g3 -Wall -c -fmessage-length = 0
代码在x86_64架构上运行。
为什么它只连接十次?
答案 0 :(得分:2)
对于重叠字符串,未定义strcpy()和strcat()的行为。因此,您对c []的两次写入都是可疑的,而不仅仅是测试粉碎堆栈,您还在测试编译器对此未定义行为的处理。
我希望strcpy(c,b)行失败,但是实现必须以某种方式得到b的长度才能在c的开头覆盖尾随的零。例如,如果它从最后一个字节复制到第一个字节,就会发生这种情况。
strcat(c,b)可以以更直接的方式实现。也许十倍的数据足以达到终止它的一些限制。
如果您想测试破坏堆栈,请不要使用这些方法。而是只使用一个数组,并用循环写过它的末尾,例如“for(i = 0; i&lt; 1000000; i ++)c [i] ='h';”
答案 1 :(得分:0)
如果您的平台使用内存保护并且其堆栈逐渐增长,例如x86(What is the direction of stack growth in most modern systems?),那么选择任何堆栈位置并从那里写入增加的地址(例如字符串...)意味着您不要不要去堆栈扩展的方向但是堆栈的起源,最终会在它上面运行并在一个非映射的保护页面上陷入死亡,在这种情况下你会得到你提到的错误信息。
错误消息可以并且以这种方式进行个性化,以便提示您发生了什么。
除此之外:更改任何内容可能会改变代码的行为,因为平台没有义务以这种方式行事。
抛开第二个:令人震惊的是,strcpy(c, b);
的行为就好像它没有覆盖从b
开始并在c
中终止的字符串的终结符。
答案 2 :(得分:-1)
我使用gcc编译器得到这样的输出:
a = abcdefghijklmnop
b =
c =
a = abcdefghijklmnopABCDEFGHIJKLMNOP
b = ABCDEFGHIJKLMNOP
c =
a = abcdefghijklmnopABCDEFGHIJKLMNOP
b = ABCDEFGHIJKLMNOP
c = ABCDEFGHIJKLMNOP
a =
b = ABCDEFGHIJKLMNOP
c = ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP
这是因为您没有为终结器提供所需的大小。试试吧:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main() {
char a[17];
char b[17];
char c[33];
strcpy(a, "abcdefghijklmnop");
printf("a = %s\nb = %s\nc = %s\n\n", a, b, c);
strcpy(b, "ABCDEFGHIJKLMNOP");
printf("a = %s\nb = %s\nc = %s\n\n", a, b, c);
strcpy(c, b);
printf("a = %s\nb = %s\nc = %s\n\n", a, b, c);
strcat(c, b);
printf("a = %s\nb = %s\nc = %s\n\n", a, b, c);
return 0;
}
现在一切都很好。 谢谢Baldrick。