How to be more careful about null pointers?

Ali Çehreli via Digitalmars-d-learn digitalmars-d-learn at puremagic.com
Mon Mar 28 23:21:49 PDT 2016


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



More information about the Digitalmars-d-learn mailing list