RAII pointers

Stanislav Blinov via Digitalmars-d-learn digitalmars-d-learn at puremagic.com
Sat Jun 3 13:05:33 PDT 2017


On Saturday, 3 June 2017 at 19:55:30 UTC, ag0aep6g wrote:
> On 06/03/2017 09:37 PM, Moritz Maxeiner wrote:
>> Of course, but AFAIK you'd need to explicitly assign it to an 
>> object, so `ptr` won't null by accident, but only by explicit 
>> programmer intent (same as overwriting the memory the object 
>> lives in via things like `memcpy`); and you can always screw 
>> things intentionally (you could also assign some invalid value 
>> to the pointer via `memcpy`).
>
> I'd say `.init` can easily happen accidentally. Especially when 
> `@disable this(this);` is involved.
>
> When you can't copy, you may have to move sometimes. But 
> std.algorithm.move overwrites the old location with `.init`, 
> assuming that `.init` can safely be destroyed.
>
> ----
> struct S
> {
>     void* ptr;
>     @disable this(this);
>     ~this() { assert(ptr !is null); /* fails */ }
> }
>
> void f(S s) {}
>
> void main()
> {
>     auto a = S(new int);
>     import std.algorithm: move;
>     f(move(a)); /* overwrites `a` with `S.init` */
> }
> ----

Yep, that's exactly why I added the null check in the example. If 
the struct has a postblit or a destructor, `move` will be 
destructive, and will overwrite the source with .init. Sometimes 
it doesn't matter (i.e. free() is allowed to take a null 
pointer), but in general, for things like smart pointers where 
you'd do arbitrary access in destructor, it's a good habit to 
check for .init values first, in case the object has been moved.


More information about the Digitalmars-d-learn mailing list