Live data from Hacker News

Understanding Memory Management, Part 1: C

educatedguesswork.org

31–40 of 95 posts

Re: Understanding Memory Management, Part 1: C

#31
post #30
post #29

Earlier quoted context omitted.

"weakly-bound symbol" implies your a using a complex runtime library/binary format (like ELF). A portable and clean design for a library is to allow to override the internal allocator via the API (often part of the init function call). Look at vulkan3D which does many things right and doing this very part right. On the other side, you have some parts of the ALSA lib API which still requires to use the C lib free (may…

No, it doesn't mean that, because malloc can be replaced at build-time as well. But I agree that interfaces should avoid doing their own allocations and should let the caller dictate it.

Look at vulkan3D which does it right(TM).

Re: Understanding Memory Management, Part 1: C

#32

This isn't proper usage of realloc: lines = realloc(lines, (num_lines + 1) * sizeof(char *)); In case it cannot service the reallocation and returns NULL, it will overwrite "lines" with NULL, but the memory that "lines" referred to is still there and needs to be either freed or used. The proper way to call it would be: tmp = realloc(lines, (num_lines + 1) * sizeof(char *)); if (tmp == NULL) { free(lines); lines = NUL…

If you exit the program (as in the process) you don't need to free anything.

Re: Understanding Memory Management, Part 1: C

#34

This isn't proper usage of realloc: lines = realloc(lines, (num_lines + 1) * sizeof(char *)); In case it cannot service the reallocation and returns NULL, it will overwrite "lines" with NULL, but the memory that "lines" referred to is still there and needs to be either freed or used. The proper way to call it would be: tmp = realloc(lines, (num_lines + 1) * sizeof(char *)); if (tmp == NULL) { free(lines); lines = NUL…

The program abort()s if the reallocation fails. But indeed, for an educational example, it's not good to be too smart.

I believe the test if(!num_lines) is unnecessary, because reallocating a NULL pointer is equivalent to malloc(). This is also a bit "smart", but I think it is also more correct because you don't use the value of one variable (num_lines is 0) to infer the value of another (lines is NULL).

To go further, an opened-ended structure like:

    struct
    {
      unsigned count;
      char* lines[];
    };
... could also be preferable in practice. But actually writing good C is not the topic of TFA.

Re: Understanding Memory Management, Part 1: C

#36

Thanks for such a detailed article. In my spare time working with C as a hobby I am usually in "vertical mode" which is different to how I would work (carefully) at work, which is just getting things done end-to-end as fast as possible, not careful at every step that we have no memory errors. So I am just trying to get something working end-to-end so I do not actually worry about memory management when writing C. So…

> which is just getting things done end-to-end as fast as possible, not careful at every step that we have no memory errors. One horrible but fun thing a former professor of mine pointed out: If your program isn't going to live long, then you never have to deallocate memory. Once it exits, the OS will happily clean it up for you. This works in C or perhaps lazy GC languages, but for stateful objects where destructors…

There is this old chestnut about “null garbage collectors”:

https://devblogs.microsoft.com/oldnewthing/20180228-00/?p=98...

> This sparked an interesting memory for me. I was once working with a customer who was producing on-board software for a missile. In my analysis of the code, I pointed out that they had a number of problems with storage leaks. Imagine my surprise when the customers chief software engineer said "Of course it leaks". He went on to point out that they had calculated the amount of memory the application would leak in the total possible flight time for the missile and then doubled that number. They added this much additional memory to the hardware to "support" the leaks. Since the missile will explode when it hits its target or at the end of its flight, the ultimate in garbage collection is performed without programmer intervention.

Re: Understanding Memory Management, Part 1: C

#37
post #27

This isn't proper usage of realloc: lines = realloc(lines, (num_lines + 1) * sizeof(char *)); In case it cannot service the reallocation and returns NULL, it will overwrite "lines" with NULL, but the memory that "lines" referred to is still there and needs to be either freed or used. The proper way to call it would be: tmp = realloc(lines, (num_lines + 1) * sizeof(char *)); if (tmp == NULL) { free(lines); lines = NUL…

There's another bug, related to performance - this involves a quadratic amount of memory copying unless your environment can arrange for zero-copy.

Surely that's only the case if realloc() actually resizes and copies on every call? Which it normally doesn't?

I thought that most implementations of realloc() would often "round up" internally to a larger size allocation, maybe power-of-two, maybe page size, or something? So if you ask for 20 bytes, the internal bookkeeping sets aside 32, or 4096, or whatever. And then if you realloc to 24 bytes, realloc will just note that the new allocation fits in the amount its reserved for you and return the same buffer again with no copying?

Re: Understanding Memory Management, Part 1: C

#38

Thanks for such a detailed article. In my spare time working with C as a hobby I am usually in "vertical mode" which is different to how I would work (carefully) at work, which is just getting things done end-to-end as fast as possible, not careful at every step that we have no memory errors. So I am just trying to get something working end-to-end so I do not actually worry about memory management when writing C. So…

> which is just getting things done end-to-end as fast as possible, not careful at every step that we have no memory errors. One horrible but fun thing a former professor of mine pointed out: If your program isn't going to live long, then you never have to deallocate memory. Once it exits, the OS will happily clean it up for you. This works in C or perhaps lazy GC languages, but for stateful objects where destructors…

The wonders of corrupted data, stale advisory locks and UNIX IPC leftovers, because they weren't properly flushed, or closed before process termination.

Re: Understanding Memory Management, Part 1: C

#39

Thanks for such a detailed article. In my spare time working with C as a hobby I am usually in "vertical mode" which is different to how I would work (carefully) at work, which is just getting things done end-to-end as fast as possible, not careful at every step that we have no memory errors. So I am just trying to get something working end-to-end so I do not actually worry about memory management when writing C. So…

In C, not all objects need to be their own allocated entity (like they are in other languages). They can be stored in-line within another object, which means the lifetime of that object is necessarily constrained by that of its parent. You could make every object its own allocated entity, but then you're losing most of the benefits of using C, which is the ability to control memory layout of objects.

As any systems programming language include those that predate C by a decade, and still it doesn't allow full control without compiler extensions, if you really want full control of memory layout of objects, Assembly is the only way.

Re: Understanding Memory Management, Part 1: C

#40
post #12

Avoid as much as you can the C standard lib allocator, go directly to mmap system call with your own allocator if you know you won't use CPU without a MMU. If you write a library, let the user code install its own allocator.

Sure, if one doesn't care about portable code.
Post reply on HN