Live data from Hacker News

Pointers Are Complicated II, or: We need better language specs

ralfj.de

41–50 of 135 posts

Re: Pointers Are Complicated II, or: We need better language specs

#41

Earlier quoted context omitted.

And I agree, with an UB the original code is undefined and so any optimization is not right nor wrong, simply keep that UB. But then, why such a long article for a code whose second line is a UB ('p+1' is undefined)?

uintptr_t ip = (uintptr_t)(p+1); Is perfectly defined. What is undefined is converting ip back to a pointer and writing to it, which the original program never does.

[deleted]

Re: Pointers Are Complicated II, or: We need better language specs

#42
If you enjoyed learning about pointer provenance (called "safely-derived pointer" in C++ [1]), you might find the recent addition of std::launder() [2] interesting.

[1] https://en.cppreference.com/w/cpp/memory/gc/pointer_safety

[2] https://en.cppreference.com/w/cpp/utility/launder

Re: Pointers Are Complicated II, or: We need better language specs

#43
post #8

First of all: fantastic article . In-depth, insightful, and the examples are absolutely top-notch. On the razor's edge between accessible and profound. Hats off to the author. I will say that the problems seem to lie in a few interesting interlanguage quirks, and not so much on language specs . For example, LLVM and C have different definitions of "undefined behavior"[1] -- this is pointed out when looking at the `po…

> Further, I would argue that pointer provenance is a meta-language (or meta-computational) concept (which the Rust docs hint at), and logically speaking, might be intractable in the general case (I'd have to think about this more).

Unless we define provenance to only work within certain easy-to-calculate boundaries. But for the general case, sure, just don't optimize when there's uncertainty.

Re: Pointers Are Complicated II, or: We need better language specs

#45
post #40
post #21

Earlier quoted context omitted.

As usual; if a compiler knows about undefined behavior I would much rather it throw an error rather than optimize something the programmer didn't intend based on the compiler out-smarting a human's ability to be specific.

It would sometimes work but I think this (very common comment) misses the general point, there's absolutely fine and non buggy on warning-worthy code that can be optimized away if the compiler relies on UB. A very simple example: void do_stuff(int *some_ptr) { do_substuff(some_ptr); *some_ptr += 2; } static void do_substuff(int *some_ptr) { if (some_ptr != NULL) { *some_ptr = 10; } } do_stuff calls a subroutine that…

Even in your heavily contrived example, I can think of cases where the optimization isn't what the programmer wants. For instance, I might have a special handler via userfaultfd(2) that detects if I'm doing an increment of the null pointer and handles it in some special way, but can't handle just setting it to 10. For a more real example, I might have acquired a lock around do_substuff, and I might be okay with the thread segfaulting only if the lock wasn't held.

Re: Pointers Are Complicated II, or: We need better language specs

#46

Earlier quoted context omitted.

They are not always integers. See this comment from the previous discussions on the other posts, for example: https://news.ycombinator.com/item?id=17607595

> What happens when 'a' is allocated to a CPU register? When the & operator is used on 'a' it should mark it as unsafe to place the 'a' on a CPU register - CPU allocation is an optimization and optimizations should never affect how the program behaves (except making it run faster, of course) and as such they should only be applied when the compiler can be sure that they're safe to do so. (and yes, the same applies on…

That's addressed by the

> If 'b' never escapes and no (undefined) pointer arithmetic is used

part.

Re: Pointers Are Complicated II, or: We need better language specs

#47
post #5

> However, to make the argument that an optimization is correct, the exact semantics of LLVM IR (what the behavior of all possible programs is and when they have UB) needs to be documented. This is a great point as to why formal semantics of programming languages matters. Even if an optimization seems "obviously" correct, finicky things like introducing the possibility of UB can, as the post outlines, cascade into co…

Not sure why you wanted to spend the time to prove "correct optimizations can be combined", but I take issue with that proof. It only works for optimizations that give code exactly the same behavior, which is severely limiting.

Re: Pointers Are Complicated II, or: We need better language specs

#48

If you enjoyed learning about pointer provenance (called "safely-derived pointer" in C++ [1]), you might find the recent addition of std::launder() [2] interesting. [1] https://en.cppreference.com/w/cpp/memory/gc/pointer_safety [2] https://en.cppreference.com/w/cpp/utility/launder

Pointer safety is actually a separate concept from provenance. It was added to C++11 with the intent that it be used by garbage-collected implementations, but I'm not sure if anyone has ever properly implemented it. At least, the big three STL implementations have get_pointer_safety() always return pointer_safety::relaxed ("All pointers are considered valid and may be dereferenced or deallocated"), and there has been a proposal to remove pointer safety from future versions of the standard. [1]

[1] http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2020/p218...

Re: Pointers Are Complicated II, or: We need better language specs

#49

Earlier quoted context omitted.

uintptr_t ip = (uintptr_t)(p+1); Is perfectly defined. What is undefined is converting ip back to a pointer and writing to it, which the original program never does.

Hmm, I think I understand now. So now I think it's the first optimization the one that is wrong. If you replace a variable with another, don't you need to keep information of the original variable? I mean, if a==b and you do *a=1 you can replace it with *b=1, but then you need to keep the information that 'a' was written to, so other optimizations (the third one) don't think it wasn't. Or am I missing something else…

> If you replace a variable with another, don't you need to keep information of the original variable?

Note that ip and iq are integers. If you can't replace integers freely, it makes it really hard to optimize arithmetic.

Re: Pointers Are Complicated II, or: We need better language specs

#50

Does this have implications about the safety guarantees even safe Rust can make? It seems like incorrect optimization passes could result in bugs/security issues that are a byproduct of the compiler rather than the language itself. I wonder how big of an issue this is for Rust (relatively probably a bigger issue than for C/C++ where basic resource ownership bugs are more common).

This isn't the first soundness/compilations bug, it won't be the last. This bug can be fixed, hopefully with some work this whole class of bugs can be made rarer. If you were relying on your safety guarantees to include a bug free compiler - rust isn't there yet and you should stop. If you're relying on a bug free happy path, rust is as close as any other language implementation (with one or two exceptions pointed out in sibling comments).

So, I mean, if you're arguing that C/C++ programmers are culturally less repulsed by bugs... you might be right about that. Other than that I think it's about the same scale for C/C++ and rust - a bug is a bug no matter what language you wrote it in.

The only fundamental implications I think it has is that maybe we need to put more of an emphasis on formalizing the memory model if we want to reduce the number of soundness bugs (something that a number of people are already doing some awesome work towards).

Post reply on HN