Structs should not contain pointers to internal data

Ali Çehreli acehreli at yahoo.com
Mon Jun 3 09:00:58 PDT 2013


On 06/03/2013 05:26 AM, Saurabh Das wrote:

 > Thank you @Ali and @Jonothan!
 >
 > So essentially since I will be storing a pointer, Telemetry!(T) is 
NOT safe
 > to use only with structs in general.
 >
 > If I have something like:
 >
 > struct UsefulStruct2
 > {
 >      this(this) @disable;
 >      this(UsefulStruct2) @disable;
 >    this(ref const(UsefulStruct2)) @disable;
 >    ref UsefulStruct2 opAssign(UsefulStruct2) @disable;
 >    ref UsefulStruct2 opAssign(ref const(UsefulStruct2)) @disable;
 >
 >      int importantValue;
 >      auto tel1 = Telemetry!int(importantValue);
 > }
 >
 > Does that ensure that UsefulStruct2 is not relocateable and thus I can
 > safely store a pointer to importantValue?

No. The compiler can still move a struct by blit (bit level transfer). 
Blit is based on good old memcpy. For a "copy", post-blit is for making 
corrections after the fact. On the other hand, the programmer cannot 
interfere if it is a "move".

For example, rvalues are moved, e.g. to an array element as in the 
following example:

import std.stdio;
import std.array;

struct UsefulStruct2
{
     this(this) @disable;
     this(UsefulStruct2) @disable;
     this(ref const(UsefulStruct2)) @disable;
     ref UsefulStruct2 opAssign(UsefulStruct2) @disable;
     ref UsefulStruct2 opAssign(ref const(UsefulStruct2)) @disable;

     int importantValue;
     int * p;
}

UsefulStruct2 makeObject(int i)
{
     UsefulStruct2 u;
     u.importantValue = i;
     u.p = &u.importantValue;  // <-- self-referencing
     return u;
}

void main()
{
     auto arr = [ makeObject(1) ];
     assert(arr.front.p != &arr.front.importantValue);  // PASSES!
}

 > If not, what constraints do I need to add to my classes to ensure that I
 > don't run into subtle bugs when structs relocate?

As you see, @disable is cripling and not a solution for this. As far as 
I know, the only option is to observe this rule.

I agree with you that a struct may become self-referencing, unknowingly 
and indirectly through members of other types.

Ali



More information about the Digitalmars-d-learn mailing list