我試圖瞭解這個測試完全是什麼。這種玩具碼(VC++)運行時檢查未初始化的變量:測試如何實現?
int _tmain(int argc, _TCHAR* argv[])
{
int i;
printf("%d", i);
return 0;
}
編譯成這樣:
int _tmain(int argc, _TCHAR* argv[])
{ 012C2DF0推EBP
012C2DF1 MOV EBP,ESP
012C2DF3子ESP,0D8h
012C2DF9推EBX
012C2DFA推ESI
012C2DFB push edi
012C2DFC lea EDI,[EBP-0D8h]
012C2E02 MOV ECX,36H
012C2E07 MOV EAX,0CCCCCCCCh
012C2E0C代表STOS DWORD PTR ES:[EDI]
012C2E0E MOV字節的ptr [EBP-0D1h],0
int i;
printf("%d", i);
012C2E15 CMP字節的ptr [EBP-0D1h],0
012C2E1C JNE wmain + 3 BH(012C2E2Bh)
012C2E1E推12C2E5Ch
012C2E23呼叫__RTC_ UninitUse(012C10B9h)
012C2E28添加ESP,4
012C2E2B MOV ESI,尤指
012C2E2D MOV EAX,DWORD PTR [I]
012C2E30推EAX
012C2E31推12C5858h
012C2E36呼叫DWORD PTR DS:[12C9114h ]
012C2E3C添加ESP,8
012C2E3F CMP ESI,尤指
012C2E41呼叫__RTC_CheckEsp(012C1140h)
return 0;
012C2E46 XOR EAX,EAX
} 012C2E48彈出EDI
012C2E49彈出ESI
012C2E4A彈出EBX
012C2E4B ADD ESP,0D8h
012C2E51 CMP EBP,ESP
012C2E53呼叫__RTC_CheckEsp(012C1140h)
012C2E58 MOV ESP,EBP
012C2E5A彈出EBP
012C2E5B RET
的5條線EM phasized是唯一通過正確初始化變量i而被刪除的。行'push 12C2E5Ch,調用__RTC_UninitUse'調用顯示錯誤框的函數,指向包含變量名稱(「i」)的字符串作爲參數。
我無法理解是第3行執行實際測試:
012C2E0E MOV字節的ptr [EBP-0D1h],0
012C2E15 CMP字節的ptr [EBP-0D1h],0
012C2E1C jne wmain + 3Bh(012C2E2Bh)
看起來編譯器正在探測i的堆棧區域(將字節設置爲零並立即測試它是否爲零),只是爲了確保它未在某處被初始化在構建過程中無法看到。但是,探測到的地址ebp-0D1h與我的實際地址無關。
更糟的是,它似乎如果有這樣一個外部人(其他線程?)初始化這並初始化探測的地址,但零,本次測試仍然會喊的變量未初始化。
發生了什麼事?也許這個探測針對的是完全不同的東西,比如測試某個字節是否可寫?
該代碼本身正在調零它測試的位置,所以不應該採取該分支並因此打印該消息。這對我來說沒有多大意義,除非這是在沒有優化的情況下編譯的。 – Jester 2014-12-02 14:42:19
/RTC只能在未經優化的版本中生存。 – 2014-12-02 14:43:35