A flat memory model is generally easier for people to understand, because it is possible to construct a simple mapping between addresses and numbers. This makes it possible to mentally model the address space as a large array and addresses as indices into that array.
In a segmented memory model, this mental image of the address space only works within a segment, but not between segments. So far, I have not found a mental model that can accurately describe a segmented memory model.
OTOH, a segmented memory model is far superior in preventing buffer overflows. The size of a segment is not fixed, but can be determined at runtime, so it is possible to allocate your buffers in dedicated segments that are sized exactly right for the buffer contained therein. Any attempt to go outside the buffer would immediately result in an error, because you are forming an illegal address. This is not possible with a flat memory model, because you might be addressing an unrelated variable that happens to be located adjacent to the buffer.
The reason that the flat memory model is used so much more probably comes from several factors:
- The better understanding by programmers
- On the x86 (including IA32) architecture, pointers within a segment are smaller and more efficient that pointers that can refer to different segments. This resulted in near and far pointers (which were a mess to work with) and a wish to keep as much as possible within one segment. In fact, IA32 has a segmented memory model, but in practice, only a single segment is ever used, giving it the appearance of a flat memory model.
- Most processors with a segmented memory model (including the x86 architecture) did not support enough different segments to really take advantage of the fact that one segment per buffer is beneficial for security.
As a side note, it can be argued that the Java VM uses a segmented memory model, where each Java object occupies its own segment.