Most likely the 32 bit per process address space limit of 4GB.
A 32 bit process can address a max of 4 GB(2^32). On Linux, there is a 3/1 memsplit by default, which means that userspace has 3 GB of those 4, and 1 GB is used internally in the kernel. On Windows, it is 2-2 by default. We are emulating the 2-2 split by mapping the area of 2-3 GB to /dev/null. This way no pointer appears in this area. Some applications accidentally cast pointers to signed integers. If apps do that, any pointer to an address > 2 GB will get corrupted. It's not a big deal because on windows apps don't get such pointers anyway due to the 2-2 split, but we have to emulate this behavior.
In the remaining 2 GB, you have a few areas reserved for things like 16 bit DOS stuff. Linux/Mac libraries in the process are loaded there. The game .exe and DLLs are loaded there, and any physical memory allocated by the game or any libraries are mapped there. Usually the graphics driver claims some space as well to map the video memory.
So the bottom line is that of the 4 GB, 2-3 GB are consumed by memory management constraints, drivers, CrossOver, the game's executables, Linux/Mac system libraries etc.
That said, if the 32 bit version of TF2 works with a 2 GB heapsize on Windows, but not on CrossOver, it could be a CrossOver bug which we should fix.
Is there any particular reason to play with the heapsize, other than "some tuning guide recommends it"? Has anyone done any benchmarking? Also keep in mind please that CrossOver users MacOS'/Linux's memory management, so not all things said in tuning guides focused on Windows are true on CrossOver. Most of them are, because it is still the same game, but some things depend on the OS as well.