C++ 溢出与越界
2016-03-16 10:11
267 查看
堆栈溢出 , 简而言之, 就是堆栈满了,还往里面塞东西。
如下一段代码:
运行结果如下:
首先解释两个概念:
ESP : 栈指针,用于指向栈帧的栈顶(下一个压入栈的活动记录的顶部),而EBP为帧指针,指向当前活动记录的底部。 栈帧可以理解整个程序栈的子栈,程序栈由子栈构成。Windows中栈的默认大小为2MB。
对于上面的两张结果图,根据 ebp指针在减小可以看出,每进入一次递归,都会增加一个栈帧(子栈)。而程序栈空间是有限的,当迭代层级过深时,就会导致栈不够用,此时如果继续递归,则会导致溢出。
那么对于如下一段代码,c1的值是多少?
结果如下:
也就是-128 ( 负数在计算机中用补码表示:反码+1).
如果继续进行加减运算,会出现什么问题?? 其实就是正常的加减法,如128的二进制是 1000 0000 ,那么在此基础上面加1就变成了 1000 0001( 即-127),那么减1呢?就是0111 1111。 如下:
但是对于1111 1111(-1),如果此时,继续+1, 那么就变成了1 0000 0000 , 而由于char是8 bit,所以对于这个情况,最高位舍去,最后结果为0000 0000。
堆栈溢出
堆栈溢出的产生的原因主要有以下几个方面递归层级过深
由于过多的函数调用,导致调用堆栈无法容纳这些调用的返回地址,一般在递归中产生。堆栈溢出很可能由无限递归(Infinite recursion)产生,但也可能仅仅是过多的堆栈层级。如下一段代码:
void foo(){ int a; foo(); } int main() { foo(); return 0; }
运行结果如下:
首先解释两个概念:
ESP : 栈指针,用于指向栈帧的栈顶(下一个压入栈的活动记录的顶部),而EBP为帧指针,指向当前活动记录的底部。 栈帧可以理解整个程序栈的子栈,程序栈由子栈构成。Windows中栈的默认大小为2MB。
对于上面的两张结果图,根据 ebp指针在减小可以看出,每进入一次递归,都会增加一个栈帧(子栈)。而程序栈空间是有限的,当迭代层级过深时,就会导致栈不够用,此时如果继续递归,则会导致溢出。
大数据结构的局部变量
局部变量存储在栈区,如果局部变量的sizeof过大,也将导致栈溢出。但是这种情况,实际中很难遇到。越界
在32bit系统中,char类型占用1个字节,其中signed char 的最高位表示符号,也就是只有7bit是表示数据;unsigned char则是所有bit都表示数据。所以,signed char的表示范围是 -128 ~ 127, unsigned char 的表示范围是0 ~ 255。那么对于如下一段代码,c1的值是多少?
signed char a = 128; std::bitset<sizeof(char)*8> c(a); //获得a的二进制表示法 cout << c << endl;
结果如下:
也就是-128 ( 负数在计算机中用补码表示:反码+1).
如果继续进行加减运算,会出现什么问题?? 其实就是正常的加减法,如128的二进制是 1000 0000 ,那么在此基础上面加1就变成了 1000 0001( 即-127),那么减1呢?就是0111 1111。 如下:
signed char a = 128; // -128 signed char d = a - (char)1; // 127
但是对于1111 1111(-1),如果此时,继续+1, 那么就变成了1 0000 0000 , 而由于char是8 bit,所以对于这个情况,最高位舍去,最后结果为0000 0000。
相关文章推荐
- c实现各种进制间转换
- C语言+嵌入式SQL+DB2开发经验总结
- C++设计模式——单例模式 系列
- CCameraConfig.cpp文件中define替换
- C++ char*,const char*,string的相互转换
- C++实现解析INI配置文件
- C++静态成员函数&静态数据成员
- LeetCode: 2. Add Two Numbers 【C 解题】
- C++ 标准库 vector list map使用方法
- c读写常见错误
- c++实现split函数
- C语言构建WEB管理系统(五):CGI实现上传文件
- C语言构建WEB管理系统(四):CGI程序解析POST数据
- C语言构建WEB管理系统(三):CGI程序解析GET数据
- C语言构建WEB管理系统(二):了解CGI
- C语言冒泡排序
- LeetCode: 1. Two Sum【C 解题】
- c++友元函数
- C++中文件的读写
- 51单片机——I2C总线