Struct delegate access corruption
tsbockman
thomas.bockman at gmail.com
Wed Feb 17 19:42:00 UTC 2021
On Wednesday, 17 February 2021 at 17:45:01 UTC, H. S. Teoh wrote:
> I.e., the following is NOT a good idea:
>
> struct S {
> void delegate() member;
> this() {
> member = &this.impl;
> }
> private void impl();
> }
>
> because a pointer to S is stored inside S itself, so as soon as
> S gets copied or moved, the delegate context pointer is no
> longer valid (or else points to a different copy of the struct
> than the one it will be called from).
A copy constructor and opAssign can be used to update pointers
that are relative to &this:
https://dlang.org/spec/struct.html#struct-copy-constructor
// The following program prints 9 with the copy constructor, or 7
if it is commented out:
module app;
import std.stdio;
struct Foo {
int[2] things;
private int* ptr;
this(const(int[2]) things...) inout pure @trusted nothrow
@nogc {
this.things = things;
ptr = &(this.things[0]);
}
// Copy constructor:
this(scope ref const(typeof(this)) that) inout pure @trusted
nothrow @nogc {
this.things = that.things;
this.ptr = this.things.ptr + (that.ptr - that.things.ptr);
}
// Defining a matching opAssign is a good idea, as well:
ref typeof(this) opAssign(scope ref const(typeof(this)) that)
return pure @trusted nothrow @nogc {
__ctor(that);
return this;
}
void choose(const(int) x) pure @trusted nothrow @nogc {
ptr = &(things[x]); }
@property ref inout(int) chosen() return inout pure @safe
nothrow @nogc {
return *ptr; }
}
void main() {
auto foo = Foo(3, 7);
foo.choose(1);
Foo bar = foo;
bar.things[1] = 9;
writeln(bar.chosen);
}
More information about the Digitalmars-d-learn
mailing list