微軟的C\C++編譯器老是很是的弱智,不但隨便亂插運行時函數,還隨便加進亂七八糟的引用,致使程序難以通用。例如__chkstk函數,只要你使用8120字節以上的局部變量,他就會偷偷調用(CALL)該函數, 例如
int Data[8192];
int *P=(int*)&Data;
for(int I=0;I<8192;I++,P++)
{
*P=(int)I;
} 函數
反彙編結果,在進行for循環以前,他會隱藏調用__chkstk。該函數 彙編僞代碼以下: oop
;探測堆棧
ALIGN DWORD
chkstk PROC USES EBX EDX ESI EDI mov eax,esp
mov ecx,32
@@:
sub esp, 1000H
test BYTE PTR[esp],0
loop @B
mov esp,eax
ret chkstk 測試
ENDP 命令行
其本質來講 就是訪問下堆棧,引起缺頁異常,系統檢測到這種操做後,將該頁提交
因而就能夠訪問了.
但咱們的問題有三:
1:隨便亂CALL致使代碼不可總體搬移.
2:在內核即便探測也沒用,內核堆棧只有8KB,探測也不會提交,更不會增大.
3:偷偷摸摸亂增長引用增長了調試難度. 若是咱們真的須要增大堆棧,那麼在用戶態,咱們徹底能夠ZwAllocateVirtualMemory分配10-20MB,在內核態咱們能夠用ExAllocatePoolWithTag分配幾MB,而後 mov esp,xxxxxxxx.
調試
所以這種雞肋的功能沒有必要留在程序裏.可是翻遍MSDN,沒有找到取消的辦法,最後在編譯器參數裏(項目->屬性->配置屬性->C/C++->命令行->其餘選項),找到某個參數,說明以下:編譯器
/Gs 設置堆棧檢查字節數. 咱們使用/Gs8192設置堆棧檢查字節爲8MB,經測試,對 __chkstk的調用沒有了,成功達到咱們的目的.it