6 ms·
This is the core idea: > It is [...] entirely optional to call free. If you don’t call free, memory usage will increase over time, but technically, it’s not a
by enriquto 3y ago
This is the core idea:
> It is [...] entirely optional to call free. If you don’t call free, memory usage will increase over time, but technically, it’s not a leak. As an optimization, you may choose to call free to reduce memory, but again, strictly optional.
This is beautiful! Unless your program is long-running, there's no point of ever calling free in your C programs. The system will free the memory for you when the program ends. Free-less C programming is an exhilarating experience that I recommend to anybody.
In the rare cases where your program needs to be long-running, leaks may become a real problem. In that case, it's better to write a long-running shell script that calls a pipeline of elegant free-less C programs.
- tenebrisalietum 3y agoI always thought that was one reason the UNIX terminal login process (with `getty` and `exec` to shell, getty restarting when the shell exits) was the way it was.
- f321x_ 3y ago[flagged]
- hnlmorg 3y agoIt’s definitely inelegant. But I wouldn’t say it’s entirely without merit. If you’re writing a very simple “sed” like utility then you could probably get away without freeing. That all said, the kind of problems were freeing becomes complicated is generally the kind of software that is more complex than your typical “sed” command. So the advise of not freeing doesn’t really address the domain where freeing is a risk.
- codetrotter 3y agoKind of sucks for the first person that tries to process a really big file with it. Programmer never free’d, and only ran it on files that were like some hundred megabytes big. Some poor schmuck tries to process a 15 GB file on his 8 GB RAM machine, and after running for hours it crashes because of the lack of free :(
- hnlmorg 3y agoThat’s assuming each byte and/or line item is a new allocation rather than reusing already allocated memory for lines that have already been parsed. Plus not every utility needs to consider large file usage. Eg a date/time formatter. To be clear, I’m not advocating that people shouldn’t free. Just saying things aren’t always black and white. A great example of this is one of Americas missile guidance systems famously has a memory leak. But it runs out of memory after its maximum range anyway. So the memory leak doesn’t affect the performance of the missile in any scenario. Technology is often nuanced.
- gaudat 3y agoNext thing they do is to optimize the hell out of kernel process management things until it catches up with the overhead of calling a function in a GC language.
- klyrs 3y agoIn the not-rare case where you're writing a library, or wrapping a utility, the last programmer's exhilaration is your pain.
- linkdd 3y agoIf you're writing a library, you're not writing a program. If you write a C library, it is a good practice to leave the allocations to the library user, or at least provide a way to override the library's allocator. Allowing your user to write a free-less *program*.
- MrJohz 3y agoAny large program is composed of libraries. They may not explicitly be described as libraries, or imported from external sources, but there will be abstraction boundaries somewhere. Which means that if you're writing a program, you probably are also writing one or more libraries.
- kbenson 3y agoThe difference is that if you're writing a program you know the scope of use of all libraries, whether they be externally loaded or internal abstraction boundaries, and also know the scope of use of the program, and can make a call as to whether cleanup during opetation is required.
- bluGill 3y agoNot really. In theory you can, but in practice there are parts written by a different team and you don't know the scope of there parts. I also know someone who maintains some Clinton era encryption. that code is controlled who can know about it as obsecurity was all you were allowed. There are other pathalogical cases where you can't know everything about your program-
- linkdd 3y ago
- omoikane 3y agoThis solution did not override "free" to free the extra struct, so calling free is in fact not optional but probably a bad idea. Need an extra patch: #define free(_) /* no-op */
- hamburglar 3y agoBest criticism to this tongue-in-cheek solution yet. I’ll add my own more minor criticism: it will explode if the leaksaver struct allocation ever fails because it doesn’t check the result. That does it. I am not going to use it.
- junon 3y agoNitpick: for maximum source compatibility, use this instead: #define free(_) ((void)0)
- huhtenberg 3y agoTechnically _ needs to be evaluated by the macro to support cases like free(p++).
- junon 3y agohmm right... wouldn't this work then? #define free(e) ((void)(e))
- zanderwohl 3y agoThe Zig compiler does this on purpose in some cases, iirc. Free can be a waste of time if the program is going to die in half a second from now.
- toasterlovin 3y agoYeah, I first came across this strategy as a performance optimization in something Jared Sumner wrote about Bun (which is written in Zig).
- subtra3t 3y agoLink to devblog article/tweet?
- toasterlovin 3y agoCan't find it now, sorry. Can't remember if it was in a tweet or if it was an offhand comment in Bun documentation somewhere.
- RustyRussell 3y agoHilarious! But I remember the first time I saw such a program which never freed anything: jitterbug, the simple bug tracker which ran as a CGI script. It indeed allows a very simple style! Meanwhile, use ccan/tal (https://github.com/rustyrussell/ccan/blob/master/ccan/tal/_info https://github.com/rustyrussell/ccan/blob/master/ccan/tal/_i...) and be happy :)
- ramses0 3y agoI did a watch face on pebble once... the programming style was "uncommon" when you're hardcoding the ONE watch face that is currently rendering the screen. It "felt" very leaky and illegal... but it's a watch face with limited functionality, so... shrug?
- deleted 3y ago[deleted]
- rco8786 3y agoReminds me of the HFT shop that built in Java and simply turned the garbage collector off. Then when the market closed they would restart the process for the next day.
- HideousKojima 3y agoOr the missile firmware where the missile is going to explode before they run out of memory: https://devblogs.microsoft.com/oldnewthing/20180228-00/?p=98125 https://devblogs.microsoft.com/oldnewthing/20180228-00/?p=98...
- jnwatson 3y agoThere was a certain Space Shuttle program that never returned from interrupt. At the end of its interrupt handler, it would just spin. The next interrupt would just add to the call stack. What happens when it runs out of stack? It just resets the stack pointer back to the start.
- tetromino_ 3y agoUsing warhead explosion as garbage collector might seem like a clever hack, but all it takes is an upgrade by a different team (say, adding a new engine, or longer-range sensors, or repurposing a surface-to-air missile for a surface-to-surface role), and suddenly your guidance software runs out of memory before it explodes, and your missile falls onto an an elementary school or hospital.
- HideousKojima 3y agoYou can probably double the ram (or more) again by then.
- LtWorf 3y agoAssuming you know you have to do it.
- shortrounddev2 3y ago
- marcodiego 3y agoActually that is not too far from reality. Data that will be allocated only once does not need be freed. You really only need to free memory that may increase iteratively. If the memory is not used frequently it will end up on swap without major implications. If it is used during the whole execution, it will only be freed when the program ends; there's difference if it's by a 'free' or by the OS; there's just no difference. As an example, constant data that is allocated by GNU Nano is never freed. AFAIK, the same happens when you use GTK or QT; there were even tips on how to suppress valgrind warnings when using such libs.
- weinzierl 3y agoThe go guys knew this all along, because if I understood it correctly this is what happens when you disable the garbage collector. Voila, now you can claim your garbage collector is totally optional and your language fundamentally doesn't require a garbage collector. [I love golang, and I think it's one of the best languages around. If only it had a truly optional garbage collector. But then again, it wouldn't be go I guess...]
- msla 3y agoA great way to write horrible programs. In short: If it works until it crashes, it doesn't work.
- enriquto 3y agoTFA is clearly written in jest. The provided code is not supposed to be run in production, just to illustrate how easy is to trick a "leak detector" in your debugger. You just put all your mallocs in a list, and at the end of your program you can free them all. Yet, the idea of not freeing some memory in your program is not entirely stupid. Unless your memory is allocated inside a loop of unpredictable length, it's not really necessary to ever free it. Worse: the call to "free" may even fall after your program has run successfully. Thus, avoiding the useless (but typical) freeing spree at the end of your program may make it more robust!
- didgetmaster 3y ago>In the rare cases where your program needs to be long-running, leaks may become a real problem. Where did this idea come from? I have seen leaks where a program can consume all available memory in just a few seconds because the programmer (definitely not me...) forgot to free something in a function called millions of times.
- layer8 3y agoThis is just an arena allocator scoped to the process.
- alexgartrell 3y agoA professor actually told us that freeing prior to exit was harmful, because you may spend all of that time resurrecting swapped pages for no real benefit. Counterpoint is that debugging leaks is ~hopeless unless you have the ability to prune “intentional leaks” at exit
- enriquto 3y ago> debugging leaks is ~hopeless unless you have the ability to prune “intentional leaks” at exit Not in general. It depends on your debugger. For example, valgrind distinguishes between harmless "visible leaks", memory blocks allocated from main or on global variables, and "true leaks" that you cannot free anymore. The first ones are given a simple warning by the leak detector, while the true leaks are actual errors.
- cryptonector 3y agoI had to debug a program that did just that once, long ago, and the fix was to not free on exit. The program's behavior had been that it took ~20m and then one day it ran for hours and we never found out how long it would have taken. Fortunately it was a Tcl program, and the fix was to remove `unset`s of large hash tables before exiting.
- gnufx 3y agoThe canonical free-less (or no-op free) solution is conservative GC, isn't it? Specifically the Boehm collector..
- ramshanker 3y agoNot calling free can bite in short running programs also if memory allocation is done in a loop.
- huhtenberg 3y ago> Unless your program is long-running ... or unless someone decides to convert it into a daemon "because of that ticket" and then QA goes all "oh, ah, the routing is dead, the sshd is dead and the whole box is all but bricked, what could've possibly caused that".