Memory Is Not Free!
While newer desktop machines are able to use hardware and/or Virtual Memory (VM) to somewhat take care of memory fragmentation, it is not always effective. While it differs with architecture and OS, VM is limited to somewhere between 2 and 4 GB unless your application is 64bit compliant. So, in general, yes, that means that you can run out of memory (no matter what your college instructor says). I have seen this happen often with Windows programs, most of which never check the return of a new or malloc and always assume memory is available.
On hardware like the iPhone (or pretty much any video game console) VM is either none existent or not functional enough to provide any real benefit to 3rd party applications. So just because you are working on newer hardware, don’t assume that you do not have to worry about heap fragmentation! Most programmers do not realize how badly they reduce the usable amount of RAM available to their application and simply can not understand why they can’t allocate 100K when there is 2.5 MB “available“.
Personally, I really like using handles in all of my applications and games, and use a custom handle based memory manager for this purpose in many cases, especially on “gaming devices” like the iPhone. Not only does it help with heap fragmentation, via movable memory blocks, it also has extensive debugging capabilities built in (corruption checks, leak detection, fragmentation reports, etc). My handle based memory manager is based on the Mac OS Classic memory manager, and features most of the same functionality along with some of the same limitations. The biggest “limitation” is the set amount of available memory. However, I personally see this as an advantage, because no matter what system you use you do have a limited amount of memory! Especially on gaming devices, so by being able to set that limit and have the memory manager tell you how you are using that limited amount of memory I can develop apps on a Mac OS X or Windows platform and retain the limitations of the destination device. And, even if the target is Mac OS X or Windows (or any other “modern vm” capable OS), I want to know how I am using memory. For instance, just because I have 16GB of RAM on my Mac/Win machine (I actually do have that much RAM), it does not mean everyone does. Everyone also does not have 2TB of HD space available for VM. And, in the end, if I have to use VM for my application, am I really providing the end user the best experience? I don’t think so!
By using handles I am able to provide all of the same functionality of new/malloc while at the same time offering improved performance (up to 1000% faster on mobile devices, where standard memory managers often suck hard), provide the application the ability to better manage it’s memory pools, avoid fragmentation of available memory, provide the application an easy way to use multiple memory pools, and get very detailed debugging information on memory usage.
Files Benefit too!
Instead of straight file use, or a .zip archive pak system, I use a Resource Manager equivalent as well, since using a bunch of files on these devices can literally kill performance. (ie, 5 minute load times to to 1/2 minute simply by bundling all files into a resource file on a Nokia N95 – opening and closing files can be extremely slow on non-desktop hardware). Now I don’t actually use file forks, but one or more typical “data” files that use a storage system similar (but not identical) to the Apple resource format.
The benefit to this is that data can be compressed on disk, reducing storage size and (often greatly) decreasing load times, providing the ability to override existing “default” data simply by dropping in a new file (similar to the way Quake .pak files work), etc.
But in terms of memory, the resource manager provides another benefit, in that all data is provided via handles, which means there is a way to provide cheap and easy caching (ie, if a data resource is already loaded, no need to load it again, just return the existing reference), and significantly less heap fragmentation via the use of handles for relocatable data and by putting resource data in “high” memory, while all “pointer” (ie, malloc/new style allocations) are in “low” memory.