Live data from Hacker News

Memory management in C programs (2014)

nethack4.org

41–50 of 106 posts

Re: Memory management in C programs (2014)

#41

Earlier quoted context omitted.

How about in constructors?

If a constructor can fail, don't make that constructor public. Instead, add a trivial constructor to allocate an empty instance of the object, then make your possibly-failing constructor a factory function that takes whatever arguments you would pass to the constructor and returns an error code. The object being "constructed" should then be passed by reference as one of the arguments to the factory function and fille…

Constructors are resource allocation, so they can always fail.

Re: Memory management in C programs (2014)

#42

Earlier quoted context omitted.

If a constructor can fail, don't make that constructor public. Instead, add a trivial constructor to allocate an empty instance of the object, then make your possibly-failing constructor a factory function that takes whatever arguments you would pass to the constructor and returns an error code. The object being "constructed" should then be passed by reference as one of the arguments to the factory function and fille…

Constructors are resource allocation, so they can always fail.

You can't really tell if the stack overflowed in a constructor though, plus that will essentially /never/ happen, so I think it's okay to exclude stack overflows when creating stack allocated objects as failure conditions. In that case no, a lot of constructors won't be able to fail.

Re: Memory management in C programs (2014)

#43
post #14
post #11

I'm going to claim that the problem being solved here fundamentally comes from attempting to shoehorn early exit into an ancient codebase that wasn't designed for it, via longjmp. Exceptions can be a handy language feature, but plenty of modern code written in languages like C++ (whose exception support is often eschewed) and Go gets by without them. It just has to be written so that most functions manually propagate…

Yeah, I'm surprised they mentioned using longjmp for "exceptions". I think that just shows the age of the nethack codebase - maybe when it was being written people were trying to find ways of incorporating those error handling ideas into C. I doubt any modern C programmers would seriously consider using it over just returning an error code.

Error codes and longjmp are complementary methods of exception handling. Error codes can't handle every circumstance (well, at least not without undue pain). For example, error codes don't deal with nonblocking i/o or coroutines very well.

Re: Memory management in C programs (2014)

#44

Earlier quoted context omitted.

How about in constructors?

If a constructor can fail, don't make that constructor public. Instead, add a trivial constructor to allocate an empty instance of the object, then make your possibly-failing constructor a factory function that takes whatever arguments you would pass to the constructor and returns an error code. The object being "constructed" should then be passed by reference as one of the arguments to the factory function and fille…

std::optional is now confirmed for C++17, which can make the API a bit nicer. Using factory functions as pseudo-constructors also lets you name them, which is often nicer than having to rely on argument types to disambiguate constructors with different purposes.

Re: Memory management in C programs (2014)

#45
post #42

Earlier quoted context omitted.

Constructors are resource allocation, so they can always fail.

You can't really tell if the stack overflowed in a constructor though, plus that will essentially /never/ happen, so I think it's okay to exclude stack overflows when creating stack allocated objects as failure conditions. In that case no, a lot of constructors won't be able to fail.

Any function can overflow the stack. If the object is constructed on the heap, 'new' can fail but will always throw an exception; if you aren't using exceptions it will just crash the process.

Re: Memory management in C programs (2014)

#46

Earlier quoted context omitted.

And above us is probably FORTRAN and above them is probably COBOL. Actually, I think assembly language would probably be the next age "peak". If you know Asm you'll be far better at C; things like pointers and indirection immediately make sense. The effect is weaker, but still there in the other direction. (FYI, FORTRAN predates COBOL by a few years.)

> If you know Asm you'll be far better at C; things like pointers and indirection immediately make sense. Be sure not to confuse cause and effect there: if you managed to learn ASM, you must not be the sort of programmer who is confused by pointers and indirection.

Somehow tens of thousands of people from the 60s to the 90s managed to learn asm, so I highly doubt that's the direction the cause and effect goes. Assembly isn't particularly complicated, just tedious.

Re: Memory management in C programs (2014)

#47
post #32

Earlier quoted context omitted.

> plenty of modern code written in languages like C++ (whose exception support is often eschewed) and Go gets by without [exceptions]. I would not consider C++ code that eschews exceptions "modern". To eschew exceptions almost always entails giving up RAII, and if you give up RAII you've done yourself a huge disservice: you're now stuck manually managing memory and resources, and suffering all the bugs that come with…

I've not seen a large production C++ code base that did anything with exceptions other than to catch them, record some debug information and restart. This is especially true when third party code is involved. C++ is hard enough to get right without exceptions; dealing with failure in bodies of code that you didn't write and maybe don't have control over (or even source code of) is death on wheels. If that means the c…

I've seen exception classes split into recoverable and non-recoverable. The former clean up as they propagate and move the application to an initial known state in a state machine.

This works fine. I think the worst bug was an exception thrown from the initial state which lead to an infinite loop.

Re: Memory management in C programs (2014)

#48
In my opinion, writing code that consists of malloc/free pairs is inviting all the problems RAII and garbage collectors were designed to solve and which rust can now statically check for correctness. So that's basically it: at this point, I don't use the heap to manage memory in C, because if I did I'd instead use either rust or, more likely, a garbage collected language. The fact is, despite going out of their way to use the stack as much as possible in this article (including copying into the stack), its sort of a wonder they didn't realise a second, manually managed stack would be easy to manage and be orthogonal to the program stack. Yes, it has a top, but so does the program stack, and so does the memory backing the heap (yes, yes, pages, et cetera). It doesn't get you all the way there, but for many small programs, which might otherwise do a lot of mallocing and freeing as it dutifully initializes and destroys objects, you can get away with just one call to malloc, and never pop the second stack. Allocate a few stacks in your stack, throw them in a free list, and now you're cooking with gas

Re: Memory management in C programs (2014)

#49
post #32

Earlier quoted context omitted.

> plenty of modern code written in languages like C++ (whose exception support is often eschewed) and Go gets by without [exceptions]. I would not consider C++ code that eschews exceptions "modern". To eschew exceptions almost always entails giving up RAII, and if you give up RAII you've done yourself a huge disservice: you're now stuck manually managing memory and resources, and suffering all the bugs that come with…

I've not seen a large production C++ code base that did anything with exceptions other than to catch them, record some debug information and restart. This is especially true when third party code is involved. C++ is hard enough to get right without exceptions; dealing with failure in bodies of code that you didn't write and maybe don't have control over (or even source code of) is death on wheels. If that means the c…

They make it easier to diagnose crashes by providing more context than just an error code without extra effort (like a call stack). Fail fast is another option but that takes control away from the caller.

Re: Memory management in C programs (2014)

#50

Earlier quoted context omitted.

malloc+strcpy is standard C, strdup is not.

While I agree, strdup is POSIX. In the exceedingly rare event that you're on a system without it, it's simple enough to roll your own. (And if this occurred more than a couple of times, I'd roll my own anyways to keep the code obvious.)

In the exceedingly rare event that you need to target Windows?
Post reply on HN