Hacker News new | ask | show | jobs
by jakobdabo 2297 days ago
In addition to the other recommendations, make sure you fully understand the memory model of your target architecture, the stack, the heap, the linkage.

Also, understand the undefined behavior, the compiler optimizations and how it can affect your code if you forget about the UB or if you ignore the compiler warnings, and read about the `volatile` keyword.

And a personal tip, please tell the compiler not to use strict aliasing (I think it's stupid) - you will get rid of some UB without much sacrifice.

2 comments

> Also, understand the undefined behavior, the compiler optimizations and how it can affect your code if you forget about the UB or if you ignore the compiler warnings, and read about the `volatile` keyword.

PSA: volatile generally doesn't do what you want it to; you almost never want it. volatile does not "fix" undefined behavior.

> And a personal tip, please tell the compiler not to use strict aliasing (I think it's stupid) - you will get rid of some UB without much sacrifice.

This prevents the compiler from performing a number of optimizations.

Just to be clear, heap and stack are not part of C.
Then why does it make a difference whether you dereference a pointer to the stack or the heap at any point in your program?

The hardware representation of an int isn't part of C either but it most certainly had an effect on how your program will run.

Integer type representation is part of C.

See ยง6.2.6.2 in http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1256.pdf

Unsigned integers are binary, while signed integers are allowed one of three well-defined representations.

> Then why does it make a difference whether you dereference a pointer to the stack or the heap at any point in your program?

Ok, I'll bite. What difference does it make?

Because stack pointers are short lived, while heap pointers can be longer lived.

Say you have a queue of pointers that some thread is chewing on, you can't stick a pointer to a stack variable into that queue and then exit the scope of that stack variable, but you could put a longer lived heap pointer into that queue and exit the scope of the pointer, essentially passing ownership of the pointer to whatever's chewing on the other end of the queue.

Stack pointers can live just as long (for example, define some objects in main(), and they will exist for the duration of the program; hand out pointers like candy). An allocated object can be deallocated whenever.

Dereferencing said pointers isn't any different, no matter how the pointee was allocated:

    void myfun(void *foo) {
        // do things with foo.
        // how it was allocated is all the same to me
    }
As far as C is concerned, stack and heap do not exist. The validity of reference to an object is defined in terms of lifetime, which stems from its storage duration (static/automatic/allocated).

And these are concepts that just define the semantics of the language. For example, an object with automatic storage duration might never hit stack or heap or any other part of RAM; it could live in registers, or be optimized out altogether. It could be in the bss segment. The semantics also do not forbid the implementation from using mmap() or malloc() (or similar) for objects with automatic storage duration.

Using stack for automatic variables and heap for allocated variables is just one implementation technique, which should not give rise to any observable differences in the meaning of a legal program (i.e. one that doesn't go into undefined behavior) as interpreted by the abstract machine, which the standard defines.

The C standard does not talk about a heap or the stack; you could implement a "heap" by handing out pointers from the top level stack frame if you wanted to.
Is this important? By far the common case in C is using heap allocation as implemented by your libc or crt. It's pretty essential knowledge.
I guess they're not "exclusive" to C, but they're very important in C in a way they aren't in most languages. So I think op's advice here is good.