www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Access Violation in safe Code

reply Matt Elkins <notreal fake.com> writes:
Title says it; I get an access violation in code marked  safe. 
Here's a minimal example:

[code]
 safe:

struct Foo(alias Callback)
{
     ~this() {Callback();}
}

unittest
{
     uint stackVar;
     alias FooType = Foo!((){++stackVar;});

     FooType[1] foos;
     foos[0] = FooType.init;
}
[/code]

This results in:
object.Error (0): Access Violation
----------------
0x00405E2A in pure nothrow  nogc  safe void 
test.__unittestL9_4().__lambda1() at <path>\test.d(12)
... more stack ...

Line 12 is the alias FooType line, where the delegate is defined.

Where is this coming from? Intuition says it is something to do 
with calling the delegate after the stack frame has popped and 
stackVar is unreachable, but I'm not seeing it. Wouldn't foos be 
destructed before the stack frame is gone?

I don't get the issue if I mark stackVar static, or if I don't 
perform the assignment to foos[0].
Jan 29
parent reply Steven Schveighoffer <schveiguy yahoo.com> writes:
On 1/29/16 11:53 PM, Matt Elkins wrote:
 Title says it; I get an access violation in code marked  safe. Here's a
 minimal example:

 [code]
  safe:

 struct Foo(alias Callback)
 {
      ~this() {Callback();}
 }

 unittest
 {
      uint stackVar;
      alias FooType = Foo!((){++stackVar;});

      FooType[1] foos;
      foos[0] = FooType.init;
 }
 [/code]

 This results in:
 object.Error (0): Access Violation
 ----------------
 0x00405E2A in pure nothrow  nogc  safe void
 test.__unittestL9_4().__lambda1() at <path>\test.d(12)
 .... more stack ...

 Line 12 is the alias FooType line, where the delegate is defined.

 Where is this coming from? Intuition says it is something to do with
 calling the delegate after the stack frame has popped and stackVar is
 unreachable, but I'm not seeing it. Wouldn't foos be destructed before
 the stack frame is gone?

 I don't get the issue if I mark stackVar static, or if I don't perform
 the assignment to foos[0].
This looks like a bug in the compiler. It appears that Foo.init as an rvalue destroying itself results in a call into an invalid stack. It doesn't require a lambda, or a fixed-size array. And it doesn't require the stack frame holding stackVar to be invalid. This also shows the behavior: unittest { uint stackVar; void blah() { ++stackVar; } { // introduce inner scope FooType foo = FooType.init; } } https://issues.dlang.org/enter_bug.cgi -Steve
Jan 29
parent reply Matt Elkins <notreal fake.com> writes:
On Saturday, 30 January 2016 at 05:18:08 UTC, Steven 
Schveighoffer wrote:
 https://issues.dlang.org/enter_bug.cgi

 -Steve
Added! https://issues.dlang.org/show_bug.cgi?id=15627 Thanks for the help.
Jan 29
parent reply Kagamin <spam here.lot> writes:
Alias templates require stack pointer, init probably has it set 
to null.
Try this:
FooType foo = FooType();
Jan 30
parent Matt Elkins <notreal fake.com> writes:
On Saturday, 30 January 2016 at 13:37:43 UTC, Kagamin wrote:
 Alias templates require stack pointer, init probably has it set 
 to null.
 Try this:
 FooType foo = FooType();
Yes, that fixed it. Interesting.
Jan 30