On 03/28/2016 11:00 PM, cy wrote:

> struct Database {
>    string derp;
>    Statement prepare(string s) {
>      return Statement(1234);
>    }
> }
>
> struct Statement {
>    int member;
>    void bind(int column, int value) {
>      import std.stdio;
>      writeln("derp",member);

Change that to &member and it will not segfault. It will print a value as low as 20. Your program is thinking that the Statement object is at address 20. :(

>    }
>
> }
>
>
> class Wrapper {
>    Database something;
>    Statement prep;
>    this() {
>      something = Database("...");
>      prep = something.prepare("...");
>    }
> }
>
> Wrapper oops;
> void initialize() {
>    oops = new Wrapper();
> }
>
> class Entry {
>    Wrapper parent;
>    this(Wrapper parent) {
>      //this.parent = parent;
>      //oops
>      parent = parent;
>    }
>    void usefulmethod() {
>      parent.prep.bind(1,42);

parent.prep.bind is translated to the following by the compiler:

"Call bind() for the object at address... let's calculate... Wherever parent is, we should add the offset of prep inside that object."

Since 'parent' is a class reference, implemented in terms of a CPU pointer, which happens to be uninitialized, meaning that its value is 0, the overall address is the following on my machine:

  0 + 20

As you've observed, the program never accesses location 0 for 'parent', rather, calculates the member starting with 'parent' and tries to access a location inside the first page, which is reserved by the operating system to catch exactly situations like this.

Ali

Reply via email to