Live data from Hacker News

Memory management in C programs (2014)

nethack4.org

61–70 of 106 posts

Re: Memory management in C programs (2014)

#61
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…

A colleague of mine is working on a C++ Qt application which can encounter failures in many different ways. It is not feasible to restart the application, the user must get a proper error message instead. He didn't use exceptions because Qt doesn't use them (it returns "empty" objects instead) and.. well, error-handling without exceptions is brittle.

In hindsight, he should have coded the logic/business part in "modern" C++ with exceptions and implemented thin adapters to the GUI part. That's what I did in another piece of code, and am extremely happy with the outcome.

It's not even hard to get them right, "the lightbulb" lit up for me after reading the chapter on exceptions in Stroustrup's TC++PL.

Re: Memory management in C programs (2014)

#62
post #32

Earlier quoted context omitted.

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…

> C++ is hard enough to get right without exceptions In what manner? If you use exceptions, you must (IMO) use RAII, or yes, it will be painful. Every example of "painful C++" I've seen involved someone ignoring that, and that is fighting the language. I understand that's a bit of a strawman argument, but you didn't elaborate enough in your post to debate it. If you are using RAII, exceptions shouldn't be terribly ha…

>> C++ is hard enough to get right without exceptions > In what manner?

I guess he's referring to noexcept/basic/strong exception guarantees. Yes, writing code with strong guarantees is hard, but what makes it hard is that you have to write your code "transactionally", i.e., either 1) prepare changes and "commit" them in one go, or 2) roll back changes if an exception occurs.

But writing code with "strong guarantee" is just as hard, if not harder, with error codes.

Re: Memory management in C programs (2014)

#63
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…

Go still has (slow, dynamic) unwinding for the express purpose of resource management. While I can't advocate for using it directly, it is enough of a concern to include in the core language.

Re: Memory management in C programs (2014)

#64
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…

> 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…

How does RAII deal with reference loops? It is trivial to create a loop of owned pointers in memory that never decrement, and it isn't that unusual of a pattern not to be a concern.

Just curious; I used a combination of strong/weak reference counting when I dealt with this. It wasn't fast, but it did appear to be less prone to implicit leaking.

Re: Memory management in C programs (2014)

#65
> In C++, the use of RAII means that exceptions can be made to free any dynamically allocated objects whose owners went out of scope as a result of the exception. In C, we don't easily have that option available to us, and those objects are just going to stay allocated.

In GCC and Clang, there is the "cleanup" attribute which runs a user-supplied function once a variable goes out of scope, so you can have scope-based destructors:

    static void do_cleanup(char **str) {
        free(*str);
    }

    void f(void) {
        char *s __attribute__((__cleanup__(do_cleanup))) = malloc(20);
        // s gets freed once the function exits
    }

Re: Memory management in C programs (2014)

#66
post #64

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…

How does RAII deal with reference loops? It is trivial to create a loop of owned pointers in memory that never decrement, and it isn't that unusual of a pattern not to be a concern. Just curious; I used a combination of strong/weak reference counting when I dealt with this. It wasn't fast, but it did appear to be less prone to implicit leaking.

One method is using weak_ptr.

Re: Memory management in C programs (2014)

#67
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…

> 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…

RAII (or rather the only useful part of the idea: that the destructor is called when an object goes out of scope) without exceptions is totally fine if you're not too dogmatic about initialising everything (especially not things that can go wrong) in the constructor but instead have one or more separate init methods with a return value. The only important part is to cleanup everything in the destructor. This is all IMHO of course, but I've been writing C++ code for 20 years just fine without ever thinking 'gee it would be nice to use exceptions here'.

Re: Memory management in C programs (2014)

#68

> In C++, the use of RAII means that exceptions can be made to free any dynamically allocated objects whose owners went out of scope as a result of the exception. In C, we don't easily have that option available to us, and those objects are just going to stay allocated. In GCC and Clang, there is the "cleanup" attribute which runs a user-supplied function once a variable goes out of scope, so you can have scope-based…

Which is inherently not portable across other C compilers.

Re: Memory management in C programs (2014)

#69

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.

No because in x86-64 assembly main memory is effectively just a very big byte array and a "pointer" is just a index into that array. In C a pointer can be many different things depending on the underlying architecture.

When Intel made their 16bit cpus they still could address 20bit of memory so they decided to create the DS (current segment) and DX (offset) register.

The problem with far pointers is that they could have different values but point the same physical address and C still carries that legacy with it in the form of undefined behaviour which makes everything needlessly complex.

Re: Memory management in C programs (2014)

#70
post #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 t…

Yes because pretending it does not exist and not understanding how things worked prior to rust is totally realistic.

For all the good things Rust brings, one should not forget Rust isn't the first language having RAII, regions or being memory safe for systems programming by default.
Post reply on HN