5 ms·
It's not like UB is some magic functions that gets called when encountering UB. Every UB could verry well be wrapped in error checking and we could have 0 UB o
by Xeamek 2y ago
It's not like UB is some magic functions that gets called when encountering UB.
Every UB could verry well be wrapped in error checking and we could have 0 UB out there.
We don't do that, but that's because of (our) choice, not some superficial entity that poses machine when running into UB.
- gpderetta 2y ago> Every UB could very well be wrapped in error checking Not in C and C++. How would you check that a pointer is safe to dereference for example?
- Xeamek 2y agoWhat do you mean? Just check if it's not null?
- gpderetta 2y agoNot all non-null pointers are safe to dereference.
- Xeamek 2y agoLike?
- flohofwoe 2y agoOn the hardware and assembly level, all unmapped memory regions are illegal to access and will cause a segfault. In high level languages it gets a lot more complicated (look up "pointer provenance").
- planede 2y agoLike one that is free'd or point to a stack object that is no longer in scope. Or one that points one past the last element of an array.
- Xeamek 2y agoIt's unsafe to do that, but it's not UB
- flohofwoe 2y agoI don't have all ca 200 UBs in my head (see https://gist.github.com/Earnestly/7c903f481ff9d29a3dd1 https://gist.github.com/Earnestly/7c903f481ff9d29a3dd1), but I'm pretty sure all types of illegal memory accesses count as UB. For instance from skimming the list: - An object is referred to outside of its lifetime (6.2.4). - The value of a pointer to an object whose lifetime has ended is used (6.2.4). - An array subscript is out of range, even if an object is apparently accessible with the given subscript (as in the lvalue expression a[1][7] given the declaration int a[4][5]) (6.5.6).
- planede 2y agoTechnically the array subscript example is UB even before the dereference. a[1][7] is equivalent to `*(a[1] + 7)` and a[1] + 7 itself is UB. (6.5.7) Additive operators > If the pointer operand and the result do not point to elements of the same array object or one past the last element of the array object, the behavior is undefined. Interestingly a[1][5] is also UB, but for the dereferencing a past-the-end pointer, not for the arithmetic.
- gpderetta 2y agoYes, that's exactly what I meant. Also, dereferencing a pointer with the wrong dynamic type. > all ca 200 UBs in my head Technically there is no enumerated set of all possible UB. Anything not explicitly defined in the standard is UB. /extremely-pedantic
- tialaramex 2y agoEffort to try to write an appendix listing all the UB and IFNDR is an ambition of WG21 but there's no specific timeline. It's a bit like that "Migrate off obsolete DB server" card that's been sat in your team's (well most teams) backlog for a couple of years. Everybody agrees it should be done... But like not this sprint. My assessment is that at their current rate WG21 is adding new UB to the language slightly faster than it's being documented for the appendix, so this won't actually finish.
- mpweiher 2y agoThis turns out not to be the case. Compilers have been known to remove exactly that sort of error checking code, as there was undefined behavior present. It's a mess.
- Xeamek 2y agoYes, I know it's not possible for a specific c++ dev to do such checks, as compilers can optimize them away. What I meant is “we (as in) the c/c++ community (or rather the specification committee)” could tomorrow decide that, lets say, all null pointer dereferences should lead to program exit. Existence of UB is a choice.
- bigcheesegs 2y agoUB is a choice in that we could require symbolic execution of of all code. This is incredibly slow, so we don't. There are many cases of UB that would be cheap to check, but there are many more that are incredibly expensive to check.