Data Type Archaeology: Why Windows and Linux View Memory Differently?
Data Type Archaeology: Engineering, Memory, and Legacy
When developing cross-platform software in C or C++, developers often encounter bizarre behaviors: code that works perfectly on Linux might overflow memory or cause type errors on Windows. The reason isn’t just the OS, but architectural decisions dating back decades.
1. The Ghost of Segmented Memory: The “L” Prefix
If you’ve seen the LPWSTR type in Windows, the “L” stands for Long. But why would a pointer need to be “long”?
The Intel 8086 Era (16-bit)
In the 80s, processors used 16-bit addresses, limiting RAM access to only 64 KB. To use more memory, Intel created Segmentation. Memory was divided into blocks (segments).
- Near Pointer (16-bit): Stored only the offset within the current segment. It was fast but “short.”
- Far Pointer / Long Pointer (32-bit): Stored the segment address + the offset. This was the “L” needed to reach anywhere in memory.
The Transition to the Flat Model
With the arrival of 32-bit (and later 64-bit), segmentation died. Memory began to be viewed as a single, continuous block.
- Today: Every pointer in Windows (whether
PSTRorLPSTR) is a 64-bit pointer. The “L” is kept only as an alias to maintain compatibility with decades-old legacy code.
2. Data Models: LP64 vs. LLP64
Why is sizeof(long) 8 on Linux and 4 on Windows? The answer lies in the choice of Data Model during the 64-bit transition.
The Linux Model: LP64
Linux (and most Unix systems) adopted the LP64 model.
- Long and Pointer are 64-bit.
This is mathematically elegant because
longmatches the natural width of the processor’s registers.
The Windows Model: LLP64
Windows adopted LLP64.
- Long Long and Pointer are 64-bit.
- Long remains 32-bit.
Why did Windows do this?
To avoid breaking legacy code. Many Windows programmers assumed that sizeof(long) == sizeof(int). If Windows changed long to 64-bit, data structures saved in files would be corrupted when read by newer versions of the programs.
3. Proof of Concept: Testing Your Architecture
Use the script below to verify how your compiler and OS handle these types in practice.
| |