Hacker News new | ask | show | jobs
by nihilist_t21 1751 days ago
Hey! The author wrote PuTTY!

That was a very informative read. I feel like I am the exact target audience: I'm coming from a programing background steeped in C# and I'm learning C from the K&R book.

2 comments

There is also the excellent “Modern C” book:

https://modernc.gforge.inria.fr

The page has a link to a free PDF version.

Never thought pointers could expire, but it makes sense.
That's a fairly common trap for new C coders. Setting a pointer to something on the stack and then returning that pointer when you exit the function. It's extra insidious because it will appear to be working fine until you call another function and then try to dereference the pointer. Then your data suddenly becomes corrupt even though your program was nowhere near it.
Unless it points to a static local variable.
This is (sort of) the idea behind Rust's lifetimes. (Rust focuses more on scope, whereas pointer expiry is more about “object lifetimes”, but it's basically the same thing.)
I don't think that's true, it's just that the lifetime of a stack object is limited by its scope. Clearly when it goes out of scope its lifetime needs to end. You can end that lifetime prematurely, for example if you drop(x) then the lifetime of x ends immediately [ in fact the implementation of drop is entirely empty, but it takes the actual x itself as a parameter, not a reference to it, and so when the empty function exits the parameter's lifetime ends and x goes away ] even though it hasn't gone out of scope in your function where you created x.

I believe once upon a time Rust needed a lot more hand-holding rather than just inferring lifetimes from scope, but in modern Rust the behaviour feels pretty natural for scopes.

Scope and lifetime are two different things, but they're related in the case of automatic (local) variables.

Scope is the region of program text in which an identifier is visible.

Lifetime is the duration during program execution in which an object (stored in memory) exists.

If you define a local variable, the scope of its identifier extends from its declaration to the end of the enclosing block; its lifetime is the execution of the enclosing block.

If you allocate an object on the heap by calling `malloc()`, its lifetime ends when its deallocated by calling `free()`.

An object defined at file scope or with the `static` keyword has a lifetime that's the entire execution of the program.

In either case, if you have a pointer to the object, that pointer becomes invalid when the object it points to reaches the end of its lifetime. (And C doesn't make it particularly difficult to cause problems by trying to access an object that no longer exists.)

Rust used to use lexical scope, but now uses scope based on the control flow graph.