Date: Fri, 12 Apr 2024 20:27:10 +0200
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;
}
The memory at "p" is used first as an int, then as a float,
or the other way round (in a non-deterministic fashion).
> 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.
Jens
> 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;
}
The memory at "p" is used first as an int, then as a float,
or the other way round (in a non-deterministic fashion).
> 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.
Jens
Received on 2024-04-12 18:27:14