After a bit of thinking, I can tell you with some degree of certainty why the 2nd example didn't crash.
When a program is executed, the crt (c runtime) pushes on the stack 3 values: the number of arguments (int
), the arguments as a char **
and the environment strings also as a char **
, then calls main
.
Now when you write your main
function, as far as I know it always reads the first 2 values and passes them to the arguments of the function, if there are any. If you include the 3rd argument, it passes the 3rd value too, otherwise it's left on the stack. So the stack at the start of the program looks like this:
+--------+
| # args |
+--------+
| args |
+--------+ <------ stack pointer
| envs |
+--------+
In the first example, you allocate the int
and the struct on the stack, then the pointer, so the full stack in the first example looks like:
+--------+
| # args |
+--------+
| args |
+--------+ <------ stack pointer
| arg | <------ your integer, initialized in code
+--------+
| ob | <------ your struct, initialized in code
+--------+
| sample | <------ your pointer, uninitalized = garbage
+--------+
So sample
is pure garbage and attempting to dereference it crashes your program.
Now in the second example, the stack looks like this:
+--------+
| # args |
+--------+
| args |
+--------+ <------ stack pointer
| sample | <------ pointer, uninitalized (!)
+--------+
The pointer is still uninitalized, but the value it overwrote is envp
, which is an actual pointer to an array: char **
. When you dereference it, you get back an array of "pointers to char", so you can overwrite it safely (as long as you don't try to treat this as the original pointer anymore). The memory is allocated and you can use it.
Now this is of course heavily implementation specific, but it seems to fit for your compiler right? You can check with gdb
that (char**)sample
indeed points to an array of environment variables before you overwrite it.
Screenshot from MSVC++ 10, in 32-bit release mode (debug mode initializes all variables forcefully to prevent this kind of stuff):