4 ms·
My C programs never consumed gigs of memory. So I (like many others I assume) made a memory manager and never freed anything. You'd ask it for memory and it k
by legohead 2y ago
My C programs never consumed gigs of memory. So I (like many others I assume) made a memory manager and never freed anything. You'd ask it for memory and it kept a list of various sizes it allocated and returned what you needed to be re-used. Freeing and allocating is slow, and error prone, so just avoid it!
- KerrAvon 2y agoA venerable and completely reasonable approach for resource-constrained environments and/or programs with very small memory requirements (kilobytes).
- adamrezich 2y agoWhat makes you think that this approach is only useful for resource-constrained circumstances?
- rwmj 2y agoYeah it's reasonable. Unfortunately if you do it, and you run tools like Coverity, it'll produces reams of complaints about how you're leaking memory :-( There was one project which was genuinely a short-lived program that never needed to free memory, but in the end I gave in and added free() statements everywhere. Otherwise we could never have got it into RHEL.
- adamrezich 2y agoWhy not just put all the free()s at the end of main() behind an #ifdef DEBUG or something?
- legohead 2y agoWhat are your issues with the memory requirements being small? One of the programs was a MUD that consumed a couple hundred megabytes, and I never had issues with it. I mentioned gigabytes because of how mine specifically worked. It allocated chunks in powers of 2, so there was some % of memory that wasn't being used. For instance, If you only need 20 bytes for a string, you got back a pointer for a chunk of 32 bytes. Being just a game, and side project, I never gave it much thought, so I'm curious to hear your input.
- nine_k 2y agoWell, it's basically an implementation of a memory allocator. But how did you determine what you could re-use? That's the hard problem, one that's equivalent to calling free() at the right time.
- legohead 2y agoWhen something would normally be freed, it calls the memory manager's version of free(), which zeroes the memory and adds it back into the appropriate available list.
- LegionMammal978 2y agoIsn't that just stacking your own allocator on top of the libc allocator, the same way the libc allocator is stacked on top of the OS's page mappings? It's often a sensible idea, of course, but I wouldn't describe it as "never freeing things", just substituting libc's malloc()/free() for your own. It's not like the libc allocator is doing something radically different from keeping lists of available and allocated memory.
- legohead 2y agolibc allocator is considered "slow" for the extra overhead it has. I'll just leave it at that as you can GPT the rest. I did some of my own testing back in the days I wrote C, and mine was significantly faster than malloc/free. It's also a way, I suppose, to ensure your program has the memory it needs, depending on how you design it. Mine basically allocates all the expected memory I need at the start, while still being able to grab more if it needs. This was more of an issue back when you shared a server with lots of others.
- LegionMammal978 2y agoOf course the libc allocator is slow, it's designed as a one-size-fits-all solution that's poorly tuned for most workloads and often doesn't get substantially updated for decades. By writing your own, you aren't avoiding an allocator, you're just avoiding the libc implementation of an allocator. (In fact, most libcs let you just redefine the malloc(), free(), and realloc() functions to point to your own allocator instead of the default one, so you don't have to rewrite all the functions calling them. E.g., the mimalloc allocator [0] can be configured as a drop-in replacement for the libc allocator.) [0] https://github.com/microsoft/mimalloc https://github.com/microsoft/mimalloc