3 ms·
How do you know it's out of bounds, in general? C pointers aren't required to store their size at runtime, and even if they did and you were inside the extent
by Jweb_Guru 5y ago
How do you know it's out of bounds, in general? C pointers aren't required to store their size at runtime, and even if they did and you were inside the extent the pointer might have already been freed due to aliasing (which can be impossible to track if your language allows integer-to-pointer casts). Of course in some obvious cases, it would be good to detect this (and many compilers try), but in cases where it's obvious isn't it better to error at compile time rather than runtime?
- nayuki 5y agoAlthough pointers don't have a size, every allocation has a size: int x; // &x would have size 1 int *y = malloc(5 * sizeof(int)); // Size 5 int *z = y + 2; // Size 3 int w[4]; // Size 4 A C compiler is allowed to track the size of objects in some hidden area, and that's what enables tools like AddressSanitizer and MemorySanitizer to exist. As for pointers to already-freed objects, it is undefined behavior to read, calculate, or compare them in any way; the only legal operation is to overwrite or dispose of the pointer.
- Jweb_Guru 5y agoI am aware of all these rules, but they don't address my question. ASAN and friends add instrumentation (at significant cost) at runtime and are imperfect, especially in multithreaded programs where accesses can race with frees. My question involved another thread (for example) freeing the pointer to an underlying allocation, which was previously in-bounds. In this case, whether it was UB to construct the pointer would depend upon whether the free was synchronized with the pointer arithmetic, which is not generally something compilers can work out in nontrivial programs (though these days this stuff is amenable to formal verification).
- nayuki 5y agoC and UB are intertwined and I don't believe there is a way to solve all problems without significant compromises. Regarding how to check pointer arithmetic under multi-threading, I like Rust's approach of multiple-readers-or-single-writer, which you can't retrofit onto C's legacy pointers that can be copied arbitrarily.