Date: Fri, 12 Apr 2024 20:42:32 +0200
Am 12. April 2024 20:27:10 MESZ schrieb Jens Maurer <jens.maurer_at_[hidden]>:
>
> On 12/04/2024 10.27, Jāāā Gustedt via Liaison wrote:
> > For C it is important that these kind of dealings are possible, not
> > because of the non-determinism, but because a storage instance that is
> > returned by `malloc` can have several effective types during its
> > lifetime.
>
> To make this specific, I think you're saying that the following
> slight modification of Davis' program is valid C:
>
> int main() {
> void *p=malloc(2*(sizeof(int)+sizeof(float)));
> const int ret= sink_i(p) + sink_f(p); // <--- see here
> free(p);
> return ret;
> }
yes
> The memory at "p" is used first as an int, then as a float,
> or the other way round (in a non-deterministic fashion).
exactly, the store operations change the effective type and the
reads then are valid
and doing this with declared objects of one or the other type would be UB
> > If it is the case that C++ supposes that a `malloc`ed storage instance
> > has a fixed type from the start (we might just not know it yet) then
> > it is not modeling C's behavior correctly, and calling C functions
> > with `malloc`ed storage from C++ becomes hazardous. You may produce
> > non-value representations for the type that C++ is expecting, or even
> > introduce aliasing where the compiler wouldn't expect it.
>
> Well, calling compiler-invisible (non-inline) functions is fairly
> safe, because C++ allows to change the type of memory using
> placement-new or a rather new function std::start_lifetime_as.
> The compiler can't know whether a function call does that or not,
> so it has to assume the worst.
maybe, yes, but I still find such differences in the object model worrisome
Jens
>
> On 12/04/2024 10.27, Jāāā Gustedt via Liaison wrote:
> > For C it is important that these kind of dealings are possible, not
> > because of the non-determinism, but because a storage instance that is
> > returned by `malloc` can have several effective types during its
> > lifetime.
>
> To make this specific, I think you're saying that the following
> slight modification of Davis' program is valid C:
>
> int main() {
> void *p=malloc(2*(sizeof(int)+sizeof(float)));
> const int ret= sink_i(p) + sink_f(p); // <--- see here
> free(p);
> return ret;
> }
yes
> The memory at "p" is used first as an int, then as a float,
> or the other way round (in a non-deterministic fashion).
exactly, the store operations change the effective type and the
reads then are valid
and doing this with declared objects of one or the other type would be UB
> > If it is the case that C++ supposes that a `malloc`ed storage instance
> > has a fixed type from the start (we might just not know it yet) then
> > it is not modeling C's behavior correctly, and calling C functions
> > with `malloc`ed storage from C++ becomes hazardous. You may produce
> > non-value representations for the type that C++ is expecting, or even
> > introduce aliasing where the compiler wouldn't expect it.
>
> Well, calling compiler-invisible (non-inline) functions is fairly
> safe, because C++ allows to change the type of memory using
> placement-new or a rather new function std::start_lifetime_as.
> The compiler can't know whether a function call does that or not,
> so it has to assume the worst.
maybe, yes, but I still find such differences in the object model worrisome
Jens
-- Jens Gustedt - INRIA & ICube, Strasbourg, France
Received on 2024-04-12 18:42:38