And as bonus there is no temporal hole where you could access a null or dangling text.
Here it is as a runnable snippet: https://godbolt.org/z/fc4Gfxrfd
Here it is as a runnable snippet: https://godbolt.org/z/fc4Gfxrfd
int main() {
struct X * owner p = malloc(sizeof(struct X));
p->text = malloc(10);
free(p->text); //object text destroyed
//p->text is on uninitialized state.
//cannot be used (except assignment)
struct X x2 = {0};
*p = x2; //x2 MOVED TO *p
x_delete(p);