堆栈大小不够导致的stack overflow问题分析

堆栈大小不够问题分析

引出问题

最近同事提供了一个dll库给我使用,写好测试代码,编译通过,运行时报出栈溢出错误
在这里插入图片描述

分析

既然vs提示stack overflow(栈溢出),那应该就是接口实现代码中的局部变量大小超过了vs编译器默认的堆栈空间大小。

由于是前人(已离职人员)写的代码,同事亦称未改动此处接口代码…
那好吧( ̄へ ̄),拿过源码…look…look


主要查看接口代码中定义的局部变量(如数组变量、结构体变量等)。。。。。。(¬_¬)瞄
由于代码中结构体定义较为复杂,那咱就先直接将接口内代码注释,然后sizeof()方法打印出结构体大小看一看。
结构体大小输出为:1932562字节 (不看不知道,一看吓一跳ᓫ(°⌑°)ǃ )。
这么大肯定会导致栈溢出咯,所以问题就在这了。


PS. 顺便说下C/C++编译的程序占用的内存分为几个部分

  1. 栈区(stack segment)
    由操作系统自动分配和释放,存放函数的参数的值,局部变量的值等。
    栈大小与编译器有关。默认情况下,visual studio 2013的栈大小为1M。在Windows下,栈是向低地址扩展的数据结构,是一块连续的内存的区域。
    也就是说栈顶的地址和栈的最大容量是系统预先规定好的,在WINDOWS下,栈的大小是一个编译时就确定的常数,如果申请的空间超过栈的剩余空间时,将提示overflow。
  2. 堆区(heap segment)
    动态分配的数据存在内存的堆里面。
    一般由程序员分配释放,若程序员不释放,程序结束时可能由系统回收 。堆的大小受限于计算机系统中有效的虚拟内存。
    它与数据结构中的堆是两回事。堆是向高地址扩展的数据结构,是不连续的内存区域。这是由于系统是用链表来存储的空闲内存地址的,自然是不连续的,而链表的遍历方向是由低地址向高地址。
  3. 全局区(静态区)(data segment)
    全局变量和静态变量的存储区域是在一起的,程序结束后由系统释放。数据区的大小由系统限定,一般很大。
    默认情况下,VS2010可容纳的全局变量数组大小是2G。由于程序本身的应用,所以只能使用小于2G大小。

解决方案

问题知道了,源头位置也找到了,接下来就是如何解决了。 解决方案有以下几种:

  1. 修改编译器中的堆栈大小。
    VS2013中修改堆栈大小如下
    在这里插入图片描述
    注意:堆栈设置仅对exe等可执行程序生效。

  2. 将数组/结构体设置为就static。
    此方案就是将空间较大的变量设置为全局变量或静态变量。

  3. 在堆上创建数组/结构体。
    此方法即通过new方式动态分配数据空间。new了就要delete,否则很容易产生内存泄露等问题。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
如何解决 Flutter 中出现的 Stack Overflow 错误? Flutter 中的 Stack Overflow 错误通常是由于递归调用等无限循环引起的。解决此问题的方法之一是检查您的代码是否存在无限循环的情况,并尝试避免使用会导致无限递归的函数、方法或操作。另一个解决问题的方法是增加 Dart 的堆栈大小限制,可以通过在 main 函数的开头设置以下代码来实现: import 'dart:io'; void main() { // 设置堆栈大小为 4MB Platform.isWindows ? _setWindowsStackSize() : _setStackSize(); } void _setWindowsStackSize() { const int size = 4 * 1024 * 1024; dynamic args = <String>[ '/c', 'REG ADD "HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\SubSystems" /v "Windows" /t REG_SZ /d "%SystemRoot%\system32\csrss.exe ObjectDirectory=\Windows SharedSection=1024,4096,2048,512,512,256,256,64,3072,180,1024 Windows=On SubSystemType=Windows" /f', '/d', '-', '/f', ]; final ProcessResult result = Process.runSync('cmd', args, runInShell: true, stdoutEncoding: SystemEncoding, stderrEncoding: SystemEncoding, inputEncoding: SystemEncoding); if (result.exitCode == 0) { args = <String>[ '/c', 'REG ADD "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Windows" /v "ProcessCommandLine" /t REG_SZ /d "$env:windir\system32\csrss.exe -ObjectDirectory \Windows -SessionManager -Embedding 1024 4096 2048 512 512 256 256 64 3072 180 1024 -WindowsSubsys" /f', '/d', '-', '/f', ]; final ProcessResult result = Process.runSync('cmd', args, runInShell: true, stdoutEncoding: SystemEncoding, stderrEncoding: SystemEncoding, inputEncoding: SystemEncoding); } } void _setStackSize() { const int size = 4 * 1024 * 1024; StackOverflowError().stackTraceLimit = size ~/ 512; } 请注意,增加堆栈大小可能会影响应用程序的性能,因此请谨慎使用并进行适当的测试。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值