It's up to the linker to build the segments, and the run-time link-loader picks the addresses - the compiler is not involved in the process.
That's a common sort of buffer overflow (it's not the only one, but it's a good example). But as long as you can't execute code in the stack or data segments, it's difficult to exploit such overflows for anything more than crashing the program (since you can only jump to existing code). When the system lets you execute from the stack or the data sections, the attacker has more flexibility since they can insert their own machine code into the program's data, then execute it.
Thus the main protection against malicious buffer overflow attacks is to ensure that the stack and data segments are marked non-executable (something Linux has had for ages, and windows has caught up with - if you enable it). Of course, that means that self-modifying code can't work, which is a problem for just-in-time compilers and certain other techniques such as trampolines.
The other protective mechanism is to randomise the addresses of the segments (supported in Linux, and possibly now in Vista?). This makes it almost impossible to pick suitable addresses when overwriting the return address on a buffer overflow, so that at best you can cause a crash but not specific malicious behaviour.
Traditionally on most architectures, you get the code first, then the statically allocated data (initialised data followed by uninitialised data), then the heap. The stack starts at the top of memory and grows downwards - the heap and stack meet in the middle when you run out of memory. On modern OS's with virtual memory, the code, data, heap and stack are often separate.