Date: Wed, 19 Feb 2025 20:08:51 +0100
Hi Filip,
the cases can be easily solved in source code.
I was reponding to them being caught in hardware.
For it to work there would have to be an actual null pointer dereference, which is not guaranteed; e.g. the hardware would only check for actual 0 (if the nullptr is represented by 0 for an C++ implementation) or use the memory management unit with the 0 page (e.g. the first 4KiB page).
It is not enough to sometimes catch an error.
If you write into the standard, that always/with try only doing a nullptr dereference leads to the exception handler being called, than that should reliably (always) work.
Currently IIRC calling a static member function on a nullptr is undefined behavior.
In practice it often works, as the code does not check for the nullptr.
If the compiler or optimizer catches that it is a nullptr, it can do anything instead before or after or instead of the call.
With making nullptr dereference throw, it has to reliably throw an exception, instead of calling the static member function (except if you make an exception in the throwing behavior for that case into the standard).
The correct call (succeeding with nullptr) is:
decltype(p1)::stMem()
instead of
p1->stMem()
Calling the member function on the type instead of on the pointer. No nullptr dereferencing with decltype.
-----Ursprüngliche Nachricht-----
Von:Filip <fph2137_at_[hidden]>
Gesendet:Mi 19.02.2025 18:22
Betreff:Re: [std-proposals] try else syntax for validity check
An:std-proposals_at_[hidden];
CC:Sebastian Wittmeier <wittmeier_at_[hidden]>; std-proposals_at_[hidden];
If we were to use:
int x // extremely large
int* ptr = nullptr;
try ptr[x];
catch (nullptr) // something safe
Should be identical to:
if (ptr != nullptr) ptr[x];
else // something safe
Dereferencing nullptr with extremely large offset seems improbable but I understand that fixing this would be connected to out of bounds checks, those can be performed with an wrapper object around the pointer.
I would just stick to wrapper objects and for those going that low level I would assume they take the risks on willingly.
——— For static member access I don’t see the issue, the same behavior should follow:
try p1->p2::stMem();
catch(nullptr) // something safe
Should be identical to:
if (p1 && p1->p2) p1->p2::stMem();
else // something safe
Accessing static members through class name should always work, unless the symbol is undefined, right?
So try className::stMem(); should never throw nullptr exception then.
——— P.S.
I’m purposely omitting the fact that in C++23 it is still not an error that x[3] and 3[x] are equivalent…
It’s just wrong to me.
Cheers, Filip
Wiadomość napisana przez Sebastian Wittmeier via Std-Proposals <std-proposals_at_[hidden]> w dniu 19 lut 2025, o godz. 05:40:
Hi Oliver,
in theory, one could either redefine pointer arithmetics and put a check for 0 there or additionally also redefine nullptr to have certain bits set or contain an additional bool.
I think that is allowed by the standard (but worsens performance).
-----Ursprüngliche Nachricht-----
Von:Oliver Hunt via Std-Proposals <std-proposals_at_[hidden]>
Gesendet:Di 18.02.2025 23:10
Betreff:Re: [std-proposals] try else syntax for validity check
An:std-proposals_at_[hidden];
CC:Oliver Hunt <oliver_at_[hidden]>;
> On Feb 18, 2025, at 11:53 AM, Jennifier Burnett via Std-Proposals <std-proposals_at_[hidden]> wrote:
>
> Actually the capability of detecting nullptr dereferences (or any invalid memory access in general) is built into pretty much all hardware nowadays. Detecting ALL nullptr references and throwing an exception would be entirely free on most machines (and in fact this is what the android java runtime does, unless they've changed it).
Producing specified behavior for a null dereference is not simply a matter of specifying the behavior of `*ptr` when ptr == nullptr, it requires specifying the behavior of `nullptr+offset`
e.g.
ptr[x] = 0
If `ptr` is null, but `x` is large enough then `ptr[x]` may be a valid address, so the only way an implementation can produce a specified outcome to the null dereference is by requiring a null check on `ptr` prior to the actual load.
I assume this latter case is why dereferencing null is UB - the trivial case of `*nullptr` is easily specifiable as EB, but once there’s a runtime offset you can’t practically define a result without requiring a null check on the base address.
—Oliver
--
Std-Proposals mailing list
Std-Proposals_at_[hidden]
https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals
--
Std-Proposals mailing list
Std-Proposals_at_[hidden]
https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals
Received on 2025-02-19 19:13:13