What am I doing wrong here?

Ali Çehreli acehreli at yahoo.com
Fri May 6 18:35:40 UTC 2022


On 5/6/22 11:04, JG wrote:
 > This isn't code to be used for anything (just understanding).

This is a segmentation fault. Reduced:

import std;

struct Delegate(A,B) {
     B function(void* ptr, A a) f;
     void* data;
     B opCall(A a) {
         return f(data,a);
     }
}

auto toDelegate(A, B,S)(S s) {
     static B f(void* ptr, A a) {
         return (*(cast(S*) ptr))(a);
     }
     Delegate!(A,B) ret;
     ret.f=&f;
     ret.data= cast(void*) &s;
     return ret;
}

void main() {
     auto a =7;
     auto h = (int b)=>a+b;
     auto d1 = toDelegate!(int,int)(h);
     d1(10);
}

This is what I did to figure out:

1) Compiled with -g

2) Started gdb (my compiled program is 'deneme'):

$ gdb --args ./deneme

3) Entered 'run' in gdb

You are storing the address of the local variable 's' here:

     ret.data= cast(void*) &s;

One good news is, compiling with -dip1000 catches this mistake. :)

Another solution is to pass 's' by ref, in which case you have to make 
sure that variable lives long enough when its used.

//                      vvv
auto toDelegate(A, B,S)(ref S s) {
   // ...
}

Further, you can mix -dip1000 and ref if you protect the code by also 
adding 'return' to the parameter:

//                      vvvvvvvvvv
auto toDelegate(A, B,S)(return ref S s) {
   // ...
}

I am surprised that 'in' does not provide similar protection.

//                      vv
auto toDelegate(A, B,S)(in S s) {

The code compiles but crashes. (?)

Ali



More information about the Digitalmars-d-learn mailing list