C 为什么此功能会导致不间断打印?

C 为什么此功能会导致不间断打印?,c,printing,infinite,C,Printing,Infinite,您好,我的一位朋友向我展示了这段代码,以说明数组/堆栈绑定检查的重要性 #include <stdio.h> void foo() { unsigned long long a[1]; a[3] -= 5; printf("Print me!\n"); } int main(){ foo(); return 0; } #包括 void foo(){ 无符号长a[1]; a[3]=5; printf(“打印我!\n”);

您好,我的一位朋友向我展示了这段代码,以说明数组/堆栈绑定检查的重要性

#include <stdio.h>

void foo() {
    unsigned long long a[1];
    a[3] -= 5;
    printf("Print me!\n");    
}

int main(){ 
    foo();
    return 0;    
}
#包括
void foo(){
无符号长a[1];
a[3]=5;
printf(“打印我!\n”);
}
int main(){
foo();
返回0;
}

当我运行这段代码时,它会一直打印“Print me!\n”,但不会停止。我已经用MingW 64位编译了代码。这里发生了什么事?我想请人给我解释一下,为什么它一直在打印文本。

看起来它可能是个错误

您正在引用堆栈数组
a
中未定义的索引。这可能会覆盖堆栈上的返回地址


当函数
返回
s到
main
函数时,它很可能再次执行
foo
,因为返回地址可能被设置为
-5
操作调用函数之前的值。

看起来它可能是一个错误

您正在引用堆栈数组
a
中未定义的索引。这可能会覆盖堆栈上的返回地址


当函数
返回
main
函数时,它很可能再次执行
foo
,因为返回地址可能被设置为
-5
操作调用函数之前的值。

您正在更改foo()中stackframe之外的值

具体来说,就是从返回地址中减去5(如果这是正常的x86-32调用约定)

如果main中的foo()调用被编译成

调用ebp-126
(调用短偏移量)指令长度为5字节

因此,返回将转到调用,而不是在调用之后返回。并且该调用将再次执行


不过,这与代码的抗移植性和未定义性差不多,因为它取决于调用约定和编译器发出的特定指令。

您正在更改foo()中stackframe之外的值

具体来说,就是从返回地址中减去5(如果这是正常的x86-32调用约定)

如果main中的foo()调用被编译成

调用ebp-126
(调用短偏移量)指令长度为5字节

因此,返回将转到调用,而不是在调用之后返回。并且该调用将再次执行


不过,这与代码一样具有抗移植性和未定义性,因为它取决于调用约定和编译器发出的特定指令因为更改变量超出数组范围。这种行为完全不可预测,在其他系统上可能会有所不同。我认为您只需修改堆栈上的返回地址即可调用printf


如果您想了解-使用反汇编程序

您通过命令
a[3]=5损坏线程堆栈因为更改变量超出数组范围。这种行为完全不可预测,在其他系统上可能会有所不同。我认为您只需修改堆栈上的返回地址即可调用printf


如果您想了解-使用反汇编程序

不,这不会导致不间断打印!未定义的行为意味着行为是未定义的。任何事情都可能发生。它会改变堆栈上的返回地址。值5很重要,因为这是调用机器代码指令的长度。因此,当函数返回时,它会跳回函数调用。像这样的黑客通常不会很好地复制。@Raj也许这取决于编译器。。。我已经用MingW 64位编译了它。@Amas,未定义的行为几乎肯定取决于编译器。事实上,它甚至可能依赖于每次编译,甚至每次运行生成的二进制文件。不,它不会导致不间断打印!未定义的行为意味着行为是未定义的。任何事情都可能发生。它会改变堆栈上的返回地址。值5很重要,因为这是调用机器代码指令的长度。因此,当函数返回时,它会跳回函数调用。像这样的黑客通常不会很好地复制。@Raj也许这取决于编译器。。。我已经用MingW 64位编译了它。@Amas,未定义的行为几乎肯定取决于编译器。事实上,它甚至可能依赖于每次编译,甚至每次运行生成的二进制文件。正确的原则,但实际上它返回到main,但地址在
foo()
调用之前更改为,因此它会再次执行。确实是未定义的行为。谢谢你。我用“print function”(打印函数)指的是
foo
,因为这是调用
printf
的函数。我已经澄清了答案。正确的原则,但实际上它返回到main,但地址更改为
foo()
调用之前的地址,因此它再次执行。确实是未定义的行为。谢谢你。我用“print function”(打印函数)指的是
foo
,因为这是调用
printf
的函数。我已经澄清了答案。