←back to thread

177 points signa11 | 1 comments | | HN request time: 0.397s | source
Show context
Arch-TK ◴[] No.42160944[source]
I have memorised the UB rules for C. Or rather, more accurately, I have memorised the subset of UB rules I need to memorise to be productive in the language and am very strict in sticking to only writing code which I know is well defined (and know my way around the C standard at a level where any obscure code I sometimes need to write can be verified to be well defined without too much hassle). I think Rust may be difficult But, if I forget something, or make a mistake, I'm screwed. Yes there's ubsan, there's tests, but ubsan and tests aren't guaranteed to work when ub is involved.

This is why I call C a minefield.

On that note, C++ has such an explosion of UB that I don't generally believe anyone who claims to know C++ because it seems to me to be almost infeasible to both learn all the rules, or at least the subset required to be productive, and then to write/modify code without getting lost.

With rust, the amount of rules I need to learn to understand rust's borrow checker is about the same or even less. And if I forget the rules, the borrow checker is there to back me up.

I still think that unless you need the performance, you should use a higher level language which hides this from you. It's genuinely easier to think about.

That being said, writing correct rust which is going to a: work as I intended and b: not have UB is much less mentally taxing, even when I have to reach for unsafe.

If you find it more taxing than writing C or C++ it's probably either because you haven't internalised the rules of the borrow checker, or because your C or C++ are riddled with various kinds of serious issues.

replies(7): >>42161052 #>>42161225 #>>42161510 #>>42162166 #>>42162494 #>>42162555 #>>42162621 #
bargainbot3k ◴[] No.42161510[source]
Embedded. Your UB is my opportunity.
replies(2): >>42161955 #>>42184081 #
1. Arch-TK ◴[] No.42184081[source]
Not really.

In embedded environments you're constrained by toolchain and platform but it's still a bad idea to rely on any behaviour which your compiler doesn't provide a definition for (which might be more behaviour than what your standard provides a definition for) because changes to the version of the compiler or even changes to surrounding code can trigger issues caused by reliance on UB.

It's not actually that hard to write embedded code which does not invoke UB outside of register access and even there it's possible to limit yourself to invoking behaviours which the combination of hardware + compiler does provide documented behaviour for.

(source: I've written embedded code which did not knowingly/intentionally invoke UB outside of register access and in those cases the implementation did define behaviour.)