www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - "Error: address of variable this assigned to this with longer

reply Nathan S. <no.public.email example.com> writes:
What is this malarky?

https://run.dlang.io/is/S42EBb

"onlineapp.d(16): Error: address of variable this assigned to 
this with longer lifetime"

```d
import std.stdio;

struct SmallString
{
     char[24] small;
     char[] data;

      disable this();

     this(scope const(char)[] s)  safe
     {
         if (s.length < small.length)
         {
             small[0 .. s.length] = s[];
             small[s.length] = 0;
             data = small[0 .. s.length];
         }
         else
         {
             assert(0, "Compilation failed before I wrote this.");
         }
     }
}

void main()
{
     writeln("Hello D");
}
```
Mar 13 2018
parent reply ag0aep6g <anonymous example.com> writes:
On Tuesday, 13 March 2018 at 20:49:16 UTC, Nathan S. wrote:
 "onlineapp.d(16): Error: address of variable this assigned to 
 this with longer lifetime"

 ```d
[...]
 struct SmallString
 {
     char[24] small;
     char[] data;
[...]
     this(scope const(char)[] s)  safe
     {
[...]
             data = small[0 .. s.length];
[...]
     }
 }
[...]
 ```
You're storing a reference to `small` in `data`. When a SmallString is copied, that reference will still point to the original `small`. When the original goes out of scope, the reference becomes invalid, a dangling pointer. Can't have those in safe code. The error message isn't exactly clear, though.
Mar 13 2018
parent reply Nathan S. <no.public.email example.com> writes:
On Tuesday, 13 March 2018 at 21:07:33 UTC, ag0aep6g wrote:
 You're storing a reference to `small` in `data`. When a 
 SmallString is copied, that reference will still point to the 
 original `small`. When the original goes out of scope, the 
 reference becomes invalid, a dangling pointer. Can't have those 
 in  safe code.

 The error message isn't exactly clear, though.
The error does not go away when restoring these lines: ``` disable this(this); disable void opAssign(this); ```
Mar 13 2018
parent reply Jonathan M Davis <newsgroup.d jmdavisprog.com> writes:
On Tuesday, March 13, 2018 21:35:50 Nathan S. via Digitalmars-d-learn wrote:
 On Tuesday, 13 March 2018 at 21:07:33 UTC, ag0aep6g wrote:
 You're storing a reference to `small` in `data`. When a
 SmallString is copied, that reference will still point to the
 original `small`. When the original goes out of scope, the
 reference becomes invalid, a dangling pointer. Can't have those
 in  safe code.

 The error message isn't exactly clear, though.
The error does not go away when restoring these lines: ``` disable this(this); disable void opAssign(this); ```
And you can't get rid of it, because the object can still be moved, which would invalidate the pointer that you have referring to the static array. As it stands, it simply does not work in D to have pointers (or dynamic arrays which refer to) member variables of structs. With the use of scope and DIP 1000, they can work within restricted circumstances, but pretty much anything that extends beyond a function call is going to have safety problems. To fix the problem, D would either need to provide a way to make it illegal for a struct to be moved (which could cause a number of problems), or it would have to provide hooks so that it would be possible to do stuff like adjust pointers when an object is moved. There's a recent discussion the problem here: https://issues.dlang.org/show_bug.cgi?id=17448 - Jonathan M Davis
Mar 13 2018
parent reply Nathan S. <no.public.email example.com> writes:
On Tuesday, 13 March 2018 at 22:33:56 UTC, Jonathan M Davis wrote:
 And you can't get rid of it, because the object can still be 
 moved, which would invalidate the pointer that you have 
 referring to the static array.
 ...
 https://issues.dlang.org/show_bug.cgi?id=17448
Thanks for the info.
Mar 14 2018
parent Jonathan M Davis <newsgroup.d jmdavisprog.com> writes:
On Wednesday, March 14, 2018 07:11:49 Nathan S. via Digitalmars-d-learn 
wrote:
 On Tuesday, 13 March 2018 at 22:33:56 UTC, Jonathan M Davis wrote:
 And you can't get rid of it, because the object can still be
 moved, which would invalidate the pointer that you have
 referring to the static array.
 ...
 https://issues.dlang.org/show_bug.cgi?id=17448
Thanks for the info.
Another way to tackle this problem is to not slice the static array but to keep track of either two indices or an index and the length explicitly and then use those with the static array. It's more annoying in some respects, but it solves the safety problem. LOL. It was actually thanks to your post here that it clicked for me that I had this problem with some of my recent code. I was well aware of the problems with having pointers to structs on the stack, but it hadn't clicked that slicing a static array like that was the same thing until you posted about it. I had realized that having a dynamic array in the struct being a slice of a static array in the struct would cause problems when the struct was copied, and I'd dealt with that with a postblit constructor, but the issue with moving didn't click until I connected the dots between your post and that recent bugzilla issue. So, answering your question actually helped me catch a bug in my code. - Jonathan M Davis
Mar 14 2018