Why can we not create trivially constructible objects using malloc if the trivial default constructor performs no action?
P0593R5 "Implicit creation of objects for low-level object manipulation" gives this example:
struct X { int a, b; };
X *make_x() {
X *p = (X*)malloc(sizeof(struct X));
p->a = 1;
p->b = 2;
return p;
}
and explains:
When compiled with a C++ compiler, this code has undefined behavior, because
p->a
attempts to write to anint
subobject of anX
object, and this program never created either anX
object nor anint
subobject.Per [intro.object]p1 (C++17 Draft N4659),
An object is created by a definition, by a new-expression, when implicitly changing the active member of a union, or when a temporary object is created.
... and this program did none of these things.
In practice this works and the UB situation is considered more as a defect in the standard than anything else. The whole objective of the paper is to propose a way to fix that issue and similar cases without breaking other things.