函数 堆栈溢出
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了函数 堆栈溢出相关的知识,希望对你有一定的参考价值。
在基于MFC创建的文档程序中,定义了某个消息响应函数,但在一开始执行此函数时就出现堆栈溢出的异常,可能是因为这个函数定义了比较多数组,有什么方法可以解决堆栈溢出问题呢(函数中必须要定义这么多数组)
在堆里分配, 用new至于所谓“必须”。。 反正我不太相信你的问题就没有替代方案 参考技术A 栈溢出还是堆溢出都没有弄清楚
怎么弄
在堆栈中找不到函数(具有溢出语句)
【中文标题】在堆栈中找不到函数(具有溢出语句)【英文标题】:Can't find the function (having the overflow statement) in the stack 【发布时间】:2011-05-23 17:57:49 【问题描述】:如果这个问题已经被问过很多次,但我已经被这个问题困扰了一段时间,请原谅。 这是具有堆栈溢出代码的函数。在调试时,我刚刚进入函数,我可以在堆栈上看到函数.. 但是当我进一步进入函数时,发生溢出,然后我在堆栈上看不到函数名。
void CCrashMeDlg::OnBnClicked_***()
int a = 10;
a = a+10;
BYTE bTemp[OneKilo * 1024];
bTemp[0] = 0;
我的问题是:
为什么一旦发生溢出,函数就会离开堆栈。 (我可以看到其他功能)。
如果我不知道代码或者代码很大,我该如何确定发生溢出的函数?
这是发生溢出后的堆栈。
0034f318 0129d640 CrashMe!_chkstk+0x27 [f:\dd\vctools\crt_bld\SELF_X86\crt\src\INTEL\chkstk.asm @ 99]
0034f328 0129d84f CrashMe!_AfxDispatchCmdMsg+0x45 [f:\dd\vctools\vc7libs\ship\atlmfc\src\mfc\cmdtarg.cpp @ 82]
0034f358 01293abe CrashMe!CCmdTarget::OnCmdMsg+0x11c [f:\dd\vctools\vc7libs\ship\atlmfc\src\mfc\cmdtarg.cpp @ 381]
0034f37c 0129a651 CrashMe!CDialog::OnCmdMsg+0x1d [f:\dd\vctools\vc7libs\ship\atlmfc\src\mfc\dlgcore.cpp @ 87]
0034f3cc 0129b2d3 CrashMe!CWnd::OnCommand+0x92 [f:\dd\vctools\vc7libs\ship\atlmfc\src\mfc\wincore.cpp @ 2675]
0034f488 01295c91 CrashMe!CWnd::OnWndMsg+0x39 [f:\dd\vctools\vc7libs\ship\atlmfc\src\mfc\wincore.cpp @ 2081]
0034f4a8 01299673 CrashMe!CWnd::WindowProc+0x24 [f:\dd\vctools\vc7libs\ship\atlmfc\src\mfc\wincore.cpp @ 2067]
0034f51c 01299702 CrashMe!AfxCallWndProc+0xac [f:\dd\vctools\vc7libs\ship\atlmfc\src\mfc\wincore.cpp @ 248]
0034f53c 75cc62fa CrashMe!AfxWndProc+0x36 [f:\dd\vctools\vc7libs\ship\atlmfc\src\mfc\wincore.cpp @ 410]
0034f568 75cc6d3a USER32!InternalCallWinProc+0x23 [d:\w7rtm\windows\core\ntuser\client\i386\callproc.asm @ 106]
0034f5e0 75cc965e USER32!UserCallWinProcCheckWow+0x109 [d:\w7rtm\windows\core\ntuser\client\clmsg.c @ 163]
0034f624 75cc96c5 USER32!SendMessageWorker+0x581 [d:\w7rtm\windows\core\ntuser\client\clmsg.c @ 717]
0034f648 71bc4601 USER32!SendMessageW+0x7f [d:\w7rtm\windows\core\ntuser\client\cltxt.h @ 795]
0034f668 71bc4663 COMCTL32!Button_NotifyParent+0x3d [d:\w7rtm\shell\comctl32\v6\button.cpp @ 2322]
0034f684 71bc44ed COMCTL32!Button_ReleaseCapture+0x113 [d:\w7rtm\shell\comctl32\v6\button.cpp @ 2424]
0034f6e4 75cc62fa COMCTL32!Button_WndProc+0xa18 [d:\w7rtm\shell\comctl32\v6\button.cpp @ 4934]
0034f710 75cc6d3a USER32!InternalCallWinProc+0x23 [d:\w7rtm\windows\core\ntuser\client\i386\callproc.asm @ 106]
0034f788 75cc77c4 USER32!UserCallWinProcCheckWow+0x109 [d:\w7rtm\windows\core\ntuser\client\clmsg.c @ 163]
0034f7e8 75cc788a USER32!DispatchMessageWorker+0x3bc [d:\w7rtm\windows\core\ntuser\client\clmsg.c @ 2591]
0034f7f8 75cec81f USER32!DispatchMessageW+0xf [d:\w7rtm\windows\core\ntuser\client\cltxt.h @ 999]
0034f824 0129c82e USER32!IsDialogMessageW+0x5f6 [d:\w7rtm\windows\core\ntuser\client\dlgmgr2.c @ 659]
0034f838 01296ba0 CrashMe!CWnd::IsDialogMessageW+0x32 [f:\dd\vctools\vc7libs\ship\atlmfc\src\mfc\winocc.cpp @ 197]
0034f844 01293a9b CrashMe!CWnd::PreTranslateInput+0x2d [f:\dd\vctools\vc7libs\ship\atlmfc\src\mfc\wincore.cpp @ 4659]
0034f858 01299144 CrashMe!CDialog::PreTranslateMessage+0xa3 [f:\dd\vctools\vc7libs\ship\atlmfc\src\mfc\dlgcore.cpp @ 81]
0034f86c 012a06f2 CrashMe!CWnd::WalkPreTranslateTree+0x23 [f:\dd\vctools\vc7libs\ship\atlmfc\src\mfc\wincore.cpp @ 3258]
0034f884 012a08dd CrashMe!AfxInternalPreTranslateMessage+0x41 [f:\dd\vctools\vc7libs\ship\atlmfc\src\mfc\thrdcore.cpp @ 233]
0034f890 012a073d CrashMe!CWinThread::PreTranslateMessage+0xd [f:\dd\vctools\vc7libs\ship\atlmfc\src\mfc\thrdcore.cpp @ 777]
0034f89c 012a092d CrashMe!AfxPreTranslateMessage+0x19 [f:\dd\vctools\vc7libs\ship\atlmfc\src\mfc\thrdcore.cpp @ 255]
0034f8ac 0129818e CrashMe!AfxInternalPumpMessage+0x2d [f:\dd\vctools\vc7libs\ship\atlmfc\src\mfc\thrdcore.cpp @ 178]
0034f8d4 012941d6 CrashMe!CWnd::RunModalLoop+0xc5 [f:\dd\vctools\vc7libs\ship\atlmfc\src\mfc\wincore.cpp @ 4714]
0034f920 01453a9f CrashMe!CDialog::DoModal+0x130 [f:\dd\vctools\vc7libs\ship\atlmfc\src\mfc\dlgcore.cpp @ 638]
0034fa20 01453987 CrashMe!CCrashMeApp::InitInstance+0x8f [d:\docs\windbg\crashme\crashme\crashme.cpp @ 64]
0034fa34 01424bc6 CrashMe!AfxWinMain+0x48 [f:\dd\vctools\vc7libs\ship\atlmfc\src\mfc\winmain.cpp @ 37]
0034fac4 76d533ca CrashMe!__tmainCRTStartup+0x11a [f:\dd\vctools\crt_bld\self_x86\crt\src\crt0.c @ 275]
0034fad0 77ce9ed2 kernel32!BaseThreadInitThunk+0xe [d:\w7rtm\base\win32\client\thread.c @ 65]
0034fb10 77ce9ea5 ntdll!__RtlUserThreadStart+0x70 [d:\w7rtm\minkernel\ntos\rtl\rtlexec.c @ 3188]
0034fb28 00000000 ntdll!_RtlUserThreadStart+0x1b [d:\w7rtm\minkernel\ntos\rtl\rtlexec.c @ 3116]
【问题讨论】:
【参考方案1】:当程序试图分配一个巨大的基于堆栈的变量时,会发生堆栈溢出。当你第一次进入函数时,程序计数器将进入函数,但它不会执行它(包括初始化和堆栈变量分配)。但是,一旦您再次进入,它将使用操作码分配堆栈变量:
sub esp, xxx; //xxx is the size of the stack variable
如果esp-xxx的结果超出栈内存页,会抛出栈溢出。因为它会在你第二次进入时立即分配堆栈变量,所以你马上就会知道你在变量声明中犯了一些错误。
解决方案是:
-
增加堆栈大小(项目设置->链接器->系统->堆栈大小)
在堆中分配变量。
递归调用次数过多也会发生堆栈溢出。大多数函数都需要在堆栈中进行一些临时存储,如果您尝试分配太多次,它将超出内存。著名的例子是递归调用自身以查找斐波那契数列的函数。当 n 超过 100000~ 时,一般(假设栈大小为 1MB,这是 VS 的默认大小)会导致栈溢出。
解决这个问题的唯一方法是增加堆栈大小。
【讨论】:
这里我知道函数,所以我把断点放在那里。如果我不知道发生溢出的函数怎么办,我将如何知道包含溢出语句的确切函数?我的意思是一旦发生溢出,我在堆栈中找不到函数名 如果你有源代码,你必须找到它。你可以通过不断进入函数来做到这一点。 或者在堆栈窗口中继续向下滚动(VS调试器)。您将看到对最后一个被调用的函数的调用。【参考方案2】:_chkstk
未建立 ebp 链并正在修改堆栈帧,这可能导致调试器无法正确展开堆栈。
如果你反汇编_chkstk,你可能会找到返回地址的存储位置。在下面的示例中,它位于ecx
寄存器中。
0:000> u ntdll!_chkstk
ntdll!_chkstk:
778fad68 51 push ecx
778fad69 8d4c2404 lea ecx,[esp+4]
778fad6d 2bc8 sub ecx,eax
778fad6f 1bc0 sbb eax,eax
778fad71 f7d0 not eax
778fad73 23c8 and ecx,eax
778fad75 8bc4 mov eax,esp
778fad77 2500f0ffff and eax,0FFFFF000h
0:000>
【讨论】:
【参考方案3】:我猜是因为以下行在堆栈上分配了很多内存:
BYTE bTemp[OneKilo * 1024];
尝试在堆上分配数据:
BYTE *bTemp = new Byte[OneKilo * 1024];
之后别忘了释放内存
【讨论】:
以上是关于函数 堆栈溢出的主要内容,如果未能解决你的问题,请参考以下文章