C++ stack overflow 局部數組變量定義超過所分配的最大空間

局部數組變量定義所分配的最大空間爲多少?如何設置大小

有兩個程序
A:

  1. #include "stdafx.h"
  2. int _tmain(int argc, _TCHAR* argv[])
  3. {
  4. int nArray[256000] = {0};
  5. nArray[1] = 5;
  6. printf("array 1 is %d",nArray[1]);
  7. return 0;
  8. }

B:

  1. #include "stdafx.h"
  2. int _tmain(int argc, _TCHAR* argv[])
  3. {
  4. int nArray[260000] = {0};
  5. nArray[1] = 5;
  6. printf("array 1 is %d",nArray[1]);
  7. return 0;
  8. }

大家通過運行可以發現,A是可以正常運行的,B雖然編譯通過了,可是當運行時就會彈出錯誤

錯誤的原因,就是棧溢出
局部變量的申請空間是存放於棧中,windows裏默認棧內存是1M

所以當申請空間大於1M時就會出現溢出錯誤

通過debug就會進入以下文件chkask.asm

page ,132
title chkstk – C stack checking routine
;***
;chkstk.asm – C stack checking routine
;
; Copyright (c) Microsoft Corporation. All rights reserved.
;
;Purpose:
; Provides support for automatic stack checking in C procedures
; when stack checking is enabled.
;
;*******************************************************************************
.xlist
include cruntime.inc
.list
; size of a page of memory
_PAGESIZE_ equ 1000h

CODESEG
page
;***
;_chkstk – check stack upon procedure entry
;
;Purpose:
; Provide stack checking on procedure entry. Method is to simply probe
; each page of memory required for the stack in descending order. This
; causes the necessary pages of memory to be allocated via the guard
; page scheme, if possible. In the event of failure, the OS raises the
; _XCPT_UNABLE_TO_GROW_STACK exception.
;
; NOTE: Currently, the (EAX < _PAGESIZE_) code path falls through
; to the "lastpage" label of the (EAX >= _PAGESIZE_) code path. This
; is small; a minor speed optimization would be to special case
; this up top. This would avoid the painful save/restore of
; ecx and would shorten the code path by 4-6 instructions.
;
;Entry:
; EAX = size of local frame
;
;Exit:
; ESP = new stackframe, if successful
;
;Uses:
; EAX
;
;Exceptions:
; _XCPT_GUARD_PAGE_VIOLATION – May be raised on a page probe. NEVER TRAP
; THIS!!!! It is used by the OS to grow the
; stack on demand.
; _XCPT_UNABLE_TO_GROW_STACK – The stack cannot be grown. More precisely,
; the attempt by the OS memory manager to
; allocate another guard page in response
; to a _XCPT_GUARD_PAGE_VIOLATION has
; failed.
;
;*******************************************************************************
public _alloca_probe
_chkstk proc
_alloca_probe = _chkstk
push ecx
; Calculate new TOS.
lea ecx, [esp] + 8 – 4 ; TOS before entering function + size for ret value
sub ecx, eax ; new TOS
; Handle allocation size that results in wraparound.
; Wraparound will result in StackOverflow exception.
sbb eax, eax ; 0 if CF==0, ~0 if CF==1
not eax ; ~0 if TOS did not wrapped around, 0 otherwise
and ecx, eax ; set to 0 if wraparound
mov eax, esp ; current TOS
and eax, not ( _PAGESIZE_ – 1) ; Round down to current page boundary
cs10:
cmp ecx, eax ; Is new TOS
jb short cs20 ; in probed page?
mov eax, ecx ; yes.
pop ecx
xchg esp, eax ; update esp
mov eax, dword ptr [eax] ; get return address
mov dword ptr [esp], eax ; and put it at new TOS
ret
; Find next lower page and probe
cs20:
sub eax, _PAGESIZE_ ; decrease by PAGESIZE
test dword ptr [eax],eax ; probe page.
jmp short cs10
_chkstk endp
end

提示棧溢出

所以解決此問題的方法就是擴大棧空間的大小

方法爲

項目->屬性->鏈接器->系統->堆棧保留大小

注:這裏填的是字節數
如果你想把他擴大爲2M的話,
1024*1024*2 = 2097152

然後再編譯運行的話A,B就都可以通過了


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章