函数 堆栈溢出

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];

之后别忘了释放内存

【讨论】:

以上是关于函数 堆栈溢出的主要内容,如果未能解决你的问题,请参考以下文章

怎么防止堆栈溢出

堆栈溢出一般是由啥原因导致的?

detours hooked CreateFile 函数触发堆栈溢出

什么是堆栈溢出?

为啥带有 setTimeout 的函数不会导致堆栈溢出

在递归函数中处理大数组时堆栈溢出