Checking for Nil Dereferences

The Chapel compiler includes two different mechanisms to check for nil dereferences. First, at compile-time, the compiler looks for places where it can prove a nil will be dereferenced or a method called on nil. When it can find such a case, it raises an error.

The second mechanism is a run-time check inserted at each method call on an object. It checks that the receiver object is not nil. These checks are on by default and can be disabled by –fast, –no-checks, or –no-nil-checks.

Example of Compile-time Nil Checking

Consider this example program:

// ex.chpl

class MyClass {
  var x: int;
  proc method() { }
}

var obj: MyClass; // default initializes obj to store nil
obj.method();

var x = new owned MyClass(1);
var y = x.release(); // now x stores nil
x.method();

Compiling this program will produce the following compilation errors:

ex.chpl:9: error: attempt to dereference nil
ex.chpl:9: note: variable obj is nil at this point
ex.chpl:8: note: this statement may be relevant
ex.chpl:13: error: attempt to dereference nil
ex.chpl:12: note: this statement may be relevant

Limitations of Compile-time Nil Checking

The compiler analysis for nil checking only does per-function analysis using very conservative alias analysis rules. It cannot detect all cases where a nil is dereferenced. Here are some limitations of the analysis:

  • it gives up in certain complex control flow situations

  • it does not track may-alias sets

  • it is not interprocedural

Nonetheless we hope that the additional checking provided by this pass is useful. If you run into a surprising case where it reports an error, please file a bug report. Also, note that using the compiler flag --no-compile-time-nil-checking will disable these checks. However, the exact nature of the checking and the name of the flag are likely to change in future releases.