[HN Gopher] Memory leak proof every C program
___________________________________________________________________
Memory leak proof every C program
Author : jandeboevrie
Score : 61 points
Date : 2024-01-19 19:30 UTC (1 days ago)
(HTM) web link (flak.tedunangst.com)
(TXT) w3m dump (flak.tedunangst.com)
| kelthan wrote:
| This solution doesn't do anything to prevent leaking memory in
| anything but the most pedantic sense, and actually creates leaks
| and dangling pointers.
|
| The function just indirects malloc with a wrapper so that all of
| the memory is traversable by the "bigbucket" structure. Memory is
| still leaked in the sense that any unfreed data will continue to
| consume heap memory and will still be inaccessible to the code
| unless the application does something with the "bigbucket"
| structure--which it can't safely do (see below).
|
| There is no corresponding free() call, so data put into the
| "bigbucket" structure is never removed, even when the memory
| allocation is freed by the application. This, by definition, is a
| leak, which is ironic.
|
| In an application that does a lot of allocations, the "bigbucket"
| structure could exhaust the heap even though there are zero
| memory leaks in the code. Consider the program:
| int main(int argc, char** argv) { for (long i = 0; i <
| 1000000; i++) { void *foo = malloc(sizeof(char) *
| 1024); free(foo); } return 0; }
|
| At the end of the million iterations, there will be zero
| allocated memory, but the "bigbucket" structure will have a
| million entries (8MB of wasted heap space on a 64-bit computer).
| And every pointer to allocated memory in the "bigbucket"
| structure is pointing to a memory address previously freed so now
| points to a completely undefined location--possibly in the middle
| of some memory block allocated later.
|
| There are already tools to identify memory leaks, such as
| LeakSanitiser https://clang.llvm.org/docs/LeakSanitizer.html. Use
| those instead.
| aidenn0 wrote:
| > There are already tools to identify memory leaks, such as
| LeakSanitiser https://clang.llvm.org/docs/LeakSanitizer.html.
| Use those instead.
|
| Clearly the author of TFA is aware of such tools, since the
| idea is to trick them.
| froh wrote:
| that's the joke...
| enriquto wrote:
| 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.
| klyrs wrote:
| In the not-rare case where you're writing a library, or
| wrapping a utility, the last programmer's exhilaration is your
| pain.
| linkdd wrote:
| If 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 wrote:
| Any 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.
| avgcorrection wrote:
| Yeah I don't know how a C library without `_free()` calls
| would work across FFI (like making bindings).
| gaudat wrote:
| Next 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.
| omoikane wrote:
| This 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 */
| tenebrisalietum wrote:
| I 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.
| zanderwohl wrote:
| The 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.
| RustyRussell wrote:
| Hilarious!
|
| 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/b
| lob/master/ccan/tal/_i...) and be happy :)
| rco8786 wrote:
| Reminds 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.
| marcodiego wrote:
| Actually 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 wrote:
| The 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...]
| deviantbit wrote:
| Where is the hand on face emoji when you need one?
| nektro wrote:
| U+1F926 U+200D U+2640 U+FE0F
| deviantbit wrote:
| Thanks.
| david2ndaccount wrote:
| This is not thread safe.
| dgan wrote:
| All arena-apologists hate this little trick
| lpapez wrote:
| I bet this is what some people on my team would come up with if
| the ticket acceptance criteria said "program must not leak memory
| when checked with valgrind"
| sgift wrote:
| That sounds painful. Unfortunately, I know the feeling.
| aidenn0 wrote:
| Goodhart's Law[1] in action!
|
| 1: https://en.wikipedia.org/wiki/Goodhart's_law
| bugbuddy wrote:
| I totally thought this was an April fools joke at first. Why is
| this front page?
| occamrazor wrote:
| Probably because some people find it funny.
| mmoll wrote:
| If only I had known this earlier in my career! They should really
| add a feature to make a hard copy of the big bucket list to
| minimize memory overhead, though.
| Sakos wrote:
| I'm concerned about how a non-zero number of people here on HN
| seem to think this is meant seriously.
| deviantbit wrote:
| What is astonishing are those that think this is a serious
| solution.
| pxx wrote:
| Thank you for playing Wing Commander!
| TillE wrote:
| I used to really struggle with memory leaks in C++, until smart
| pointers came along. I think the only leak I've investigated
| since then wound up being an actual bug in the MSVC standard
| library.
|
| OS handles and such are still an issue, but you can wrap them
| too. Thank goodness for RAII, a fantastic reason to use C++ even
| if you're otherwise writing C-like code.
| tiffanyh wrote:
| Will this land in OpenBSD, given Ted is a core dev?
| neonscribe wrote:
| Obviously this is a joke, but the real message should be: if you
| can't manage your own memory, you should be using a language
| implementation with automatic memory management. If your code
| really needs to run "close to the metal", you really need to
| figure out how to manage your memory. In 2024, language
| implementations without automatic memory management should be
| reserved for applications that absolutely need them.
| _a_a_a_ wrote:
| It obviously is a joke, but at the same time it's actually a
| viable approach for the right problem. Sometimes leaking is
| very tolerable and in terms of programmer time, very cheap!
| privatedan wrote:
| Hahahahaha I love this! Almost as good as fixing race conditions
| with sleep statements ( which I see a lot )
| Manfred wrote:
| From the comments I get the impression that we have all worked
| with someone that would have considered this an actual solution
| and we had to talk them out of it.
| zeroCalories wrote:
| While subtle, your point was not lost on me!
|
| Technically all pointers are accessible, but the issue remains
| that we have not logically accounted for unused resources and are
| wasting capacity. In this sense, memory leaks are possible in all
| languages. We could store every object into a global structure,
| and it will never be freed in any language. Thus, my Rust program
| balloons forever.
| londons_explore wrote:
| I've got an idea...
|
| We have a counter that goes up by 1 every time you call malloc.
|
| And down by one every time you call free.
|
| And when the program quits, if the counter isn't zero, an email
| is fired off and a dollar gets sent from the developers bank
| account to the users bank account...
| skrebbel wrote:
| This has been PHP's approach to memory management during its best
| decades. It's a fantastic idea for short-running processes, which
| there should be more of anyway.
| Waterluvian wrote:
| "Hey I might need that later!"
|
| Memory hoarding. I hate it but I love it.
___________________________________________________________________
(page generated 2024-01-20 23:00 UTC)