[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)