越界操作导致程序崩溃的原理

下面的程序可以正常运行,但是如果注释掉定义变量b这行代码,程序在运行时直接崩溃,请说明这种现象的原因。

int main(){

cahr *a=new char[32];

int b[8];

int c[128];

c[128]=0;

c[129]=0;

c[130]=0;

strcpy(a,"hello");

cout<<a<<endl;

}

  • 程序中显然存在内存越界问题,由于通过下标对数组元素赋值时不会自动检测下标越界,因此程序在相应的地址上进行赋值,这样造成的结果就是可能错误地修改了其他变量的值。
  • 函数的局部变量保存在栈空间中,根据栈后进先出的性质,指针a保存在栈底,占用四个字节,之后是数组b,占用32个字节,栈顶元素是数组c,占用512个字节。实际的内存布局可能稍有变化,但原则是按照变量在函数中声明的顺序依次入栈。
  • 当数组c赋值时发生了内存越界,实际改变了数组b中某些元素的值,由于程序并未对数组b中的元素进行任何操作,因此程序运行时并没有什么异常,程序也会正确地输出。
  • 如果注释掉数组b这行代码,程序运行就会出问题了。此时内存布局更加简单,栈底元素是指针a,占用4个字节,栈顶元素是数组c,占用512个字节,其中指针a指向堆中一块动态分配的内存。
  • 下面三个赋值语句由于发生了内存越界问题,赋值操作胡导致指针a的值变为0,不再指向堆空间。这时候堆中动态分配的内存没有任何指针指向它,既无法使用,也无法释放,从而导致内存泄露。
  • 由于地址编码为0的内存属于保护段,因此不能够操作这段内存,修改保护段的内存会导致程序崩溃。程序中字符串拷贝语句试图将字符串“hello”拷贝到内存为0的内存空间中,违反了保护段内存不能修改的原则,因此在执行字符串拷贝时程序崩溃。
展开阅读全文

没有更多推荐了,返回首页