(VC++) Runtime Check for Uninitialized Variables: How is the test Implemented?

assembly, compiler-construction, visual-c++, x86

Solution

Here is my guess: the compiler probably allocates flags in memory showing the initialization status of variables. In your case for variable `i` this is a single byte at `[ebp-0D1h]`. The zeroing of this byte means `i` is not initialized. I assume if you initialize `i` this byte will be set to non-zero. Try something run-time like this: `if (argc > 1) i = 1;` This should generate code instead of omitting the whole check. You can also add another variable, and see if you get two different flags.

The zeroing of the flag and the testing just happen to be consecutive in this case, but that might not always be the case.

Problem

I'm trying to understand what this test does exactly. This toy code ``` int _tmain(int argc, _TCHAR* argv[]) { int i; printf("%d", i); return 0; } ``` Compiles into this: ``` int _tmain(int argc, _TCHAR* argv[]) ``` { 012C2DF0 push ebp 012C2DF1 mov ebp,esp 012C2DF3 sub esp,0D8h 012C2DF9 push ebx 012C2DFA push esi 012C2DFB push edi 012C2DFC lea edi,[ebp-0D8h] 012C2E02 mov ecx,36h 012C2E07 mov eax,0CCCCCCCCh 012C2E0C rep stos dword ptr es:[edi] 012C2E0E mov byte ptr [ebp-0D1h],0 ``` int i; printf("%d", i); ``` 012C2E15 cmp byte ptr [ebp-0D1h],0 012C2E1C jne wmain+3Bh (012C2E2Bh) 012C2E1E push 12C2E5Ch 012C2E23 call __RTC_UninitUse (012C10B9h) 012C2E28 add esp,4 012C2E2B mov esi,esp 012C2E2D mov eax,dword ptr [i] 012C2E30 push eax 012C2E31 push 12C5858h 012C2E36 call dword ptr ds:[12C9114h] 012C2E3C add esp,8 012C2E3F cmp esi,esp 012C2E41 call __RTC_CheckEsp (012C1140h) ``` return 0; ``` 012C2E46 xor eax,eax } 012C2E48 pop edi 012C2E49 pop esi 012C2E4A pop ebx 012C2E4B add esp,0D8h 012C2E51 cmp ebp,esp 012C2E53 call __RTC_CheckEsp (012C1140h) 012C2E58 mov esp,ebp 012C2E5A pop ebp 012C2E5B ret The 5 lines emphasized are the only ones removed by properly initializing the variable i. The lines 'push 12C2E5Ch, call __RTC_UninitUse' call the function that display the error box, with a pointer to a string containing the variable name ("i") as an argument. What I can't understand are the 3 lines that perform the actual test: 012C2E0E mov byte ptr [ebp-0D1h],0 012C2E15 cmp byte ptr [ebp-0D1h],0 012C2E1C jne wmain+3Bh (012C2E2Bh) It would have seemed the compiler is probing the stack area of i (setting a byte to zero and immediately testing whether it's zero), just to be sure it isn't initialized somewhere it couldn't see during build. However, the probed address, ebp-0D1h, has little to do with the actual address of i. Even worse, it seems if there were such an external (other thread?) initialization that did initialize the probed address but to zero, this test would still shout about the variable being uninitialized. What's going on? Maybe the probe is meant for something entirely different, say to test if a certain byte is writable?

Original source