引出问题
最近同事提供了一个dll库给我使用,写好测试代码,编译通过,运行时报出栈溢出错误
分析
既然vs提示stack overflow(栈溢出),那应该就是接口实现代码中的局部变量大小超过了vs编译器默认的堆栈空间大小。
由于是前人(已离职人员)写的代码,同事亦称未改动此处接口代码…
那好吧( ̄へ ̄),拿过源码…look…look
主要查看接口代码中定义的局部变量(如数组变量、结构体变量等)。。。。。。(¬_¬)瞄
由于代码中结构体定义较为复杂,那咱就先直接将接口内代码注释,然后sizeof()方法打印出结构体大小看一看。
结构体大小输出为:1932562字节 (不看不知道,一看吓一跳ᓫ(°⌑°)ǃ )。
这么大肯定会导致栈溢出咯,所以问题就在这了。
PS. 顺便说下C/C++编译的程序占用的内存分为几个部分
- 栈区(stack segment)
由操作系统自动分配和释放,存放函数的参数的值,局部变量的值等。
栈大小与编译器有关。默认情况下,visual studio 2013的栈大小为1M。在Windows下,栈是向低地址扩展的数据结构,是一块连续的内存的区域。
也就是说栈顶的地址和栈的最大容量是系统预先规定好的,在WINDOWS下,栈的大小是一个编译时就确定的常数,如果申请的空间超过栈的剩余空间时,将提示overflow。 - 堆区(heap segment)
动态分配的数据存在内存的堆里面。
一般由程序员分配释放,若程序员不释放,程序结束时可能由系统回收 。堆的大小受限于计算机系统中有效的虚拟内存。
它与数据结构中的堆是两回事。堆是向高地址扩展的数据结构,是不连续的内存区域。这是由于系统是用链表来存储的空闲内存地址的,自然是不连续的,而链表的遍历方向是由低地址向高地址。 - 全局区(静态区)(data segment)
全局变量和静态变量的存储区域是在一起的,程序结束后由系统释放。数据区的大小由系统限定,一般很大。
默认情况下,VS2010可容纳的全局变量数组大小是2G。由于程序本身的应用,所以只能使用小于2G大小。
解决方案
问题知道了,源头位置也找到了,接下来就是如何解决了。 解决方案有以下几种:
-
修改编译器中的堆栈大小。
VS2013中修改堆栈大小如下
注意:堆栈设置仅对exe等可执行程序生效。 -
将数组/结构体设置为就static。
此方案就是将空间较大的变量设置为全局变量或静态变量。 -
在堆上创建数组/结构体。
此方法即通过new方式动态分配数据空间。new了就要delete,否则很容易产生内存泄露等问题。