C++堆栈和堆损坏

Des*_*tor 3 c++ heap-corruption stack-corruption

我最近在阅读C&C++中的堆栈和堆损坏.该网站的作者使用以下示例演示了堆栈损坏.

#include<stdio.h> 
 int main(void) 
 { 
     int b = 10; 
     int a[3]; 
     a[0] = 1; 
     a[1] = 2; 
     a[2] = 3; 

     printf(" b = %d \n",b); 
     a[3] = 12; // oops it is invalid, behaviour is undefined
     printf(" b = %d \n",b); 
     printf("address of b= %x\n",&b);
     printf("address of a[3]= %x\n",&a[3]);
     return 0; 
 }
Run Code Online (Sandbox Code Playgroud)

我在visual studio 2010编译器(VC++)上测试了上面的程序,它给了我运行时错误,说:

变量a周围的堆栈被破坏了

现在我的问题是:堆栈是否已终生损坏,或者仅在上述错误程序执行期间?

同样,我知道两次删除相同的指针可能会造成堆损坏等非常糟糕的事情.以下代码:

int* p=new int();
delete p;
delete p;  // oops disaster here, undefined behaviour
Run Code Online (Sandbox Code Playgroud)

当上面的代码片段执行时,VC++在运行时显示堆损坏错误.

Ste*_*and 7

这是未定义的行为.如果你做"禁止"的事情,你无法知道会发生什么.您无法保证您的计划能够正常运作.


Lig*_*ica 6

你必须小心这里的术语.堆栈是否会在程序的剩余时间内"损坏"?它可能是; 它可能不是.在这种情况下,您只会损坏当前堆栈帧中的数据,因此一旦您退出该函数调用,实际上您的"损坏"将会消失.

但这并非完整的故事.既然你已经覆盖了一个不应该存在的字节变量,你的程序会产生什么样的连锁效应呢?如果您通过网络连接发送此数据并且数据不再是预期的形式,则此内存损坏的后果可能会在逻辑上传递到其他功能范围,甚至其他计算机.(通常,您的数据协议将内置安全功能,以检测和丢弃意外形式的数据;但是,这取决于您.)

堆损坏也是如此.每当你覆盖不应该覆盖的东西的字节时,任何时候你使用任意或不可知的数据,你都有可能带来灾难性后果的风险,这些后果可能在逻辑上持续超出程序的生命周期.

在C++作为一种语言的范围内,这个条件总结为一个特定的短语:未定义的行为.它表明,在你破坏了你的记忆后,你根本不能真正依赖任何东西.一旦你调用了UB,所有的赌注都会被取消.

您通常在实践中保证的一个保证是您的操作系统不允许您直接覆盖任何不属于您的程序的内存.也就是说,破坏其他进程或操作系统本身的内存非常困难.现代操作系统的内存模型是故意设计的,以便保持程序隔离并防止破坏的程序和/或病毒造成这种损害.