Initializing an Immutable Field with Magic: The "Fake Placement New" Technique

ag0aep6g anonymous at example.com
Fri Jul 26 14:19:11 UTC 2019


On 26.07.19 14:36, FeepingCreature wrote:
> On Friday, 26 July 2019 at 12:12:19 UTC, ag0aep6g wrote:
>> As far as I know, we usually say that this function:
>>
>>     void f(immutable int* p)
>>     {
>>         /* ... do something with *p ... */
>>         g();
>>         /* ... do more stuff with *p ... */
>>     }
>>
>> can assume that `*p` is the same before and after calling `g`. But if 
>> unions have the power to defeat immutable, that assumption is invalid.
> 
> This is not correct, though it seems correct. This example hits the key 
> of the problem though, so well spotted.
> 
> What if `g()` manually freed `p`, then allocated some new memory, and 
> that new memory just so happened to exist at the same address? You would 
> have observed a change in the value of `p`, even though it was marked 
> immutable.
> 
> Now, this is invalid behavior, but it's not invalid behavior *of f*; the 
> entire program is just written in a way that you were able to keep one 
> pointer alive past the lifespan of the data it referenced.

It's invalid, yes. So we don't need to consider it. If the only way to 
break the assumption is to rely on undefined behavior, then there is no 
way to break the assumption.

`free`ing p and then dereferencing it has undefined behavior. It doesn't 
matter that the address happens to be reused by another allocation.

The interesting part is whether you're relying on undefined behavior 
with your union/__ctor stuff. If yes, then your code is just invalid. If 
no, then you can break the immutability assumption in a seemingly valid 
way. That would be interesting, but I'm not convinced that your code is 
valid.

The pain points:
1) The spec doesn't say clearly when union fields are considered 
initialized.
2) DMD allows @safe access of (uninitialized) immutable union fields.
3) __ctor can be called on an existing instance in @safe code. That's 
clearly a bug.



More information about the Digitalmars-d mailing list