1

Remy Lebeau stated that "There is no guarantee that accessing a nil pointer will raise an exception. It is undefined behavior. Anything could happen. An exception might be raised, or you might just read garbage, or you might trash memory, or ...". How come? In which circumstances, accessing the methods of a NIL object will NOT raise an AV AND lead to memory corruption?

// (Obj is any kind of object. Let's say TStringList) 
Obj = nil;
Obj.LoadFromFile();
Gabriel
  • 20,797
  • 27
  • 159
  • 293
  • 1
    Depends on what you mean by "access". – Uli Gerhardt Apr 29 '19 at 07:36
  • @UliGerhardt - I added an example. – Gabriel Apr 29 '19 at 07:39
  • 3
    Related: [your other question](https://stackoverflow.com/questions/51161223) – BrakNicku Apr 29 '19 at 07:39
  • @BrakNicku - the answer of that question clearly specify why SOME properties are SPECIAL. In this case, obviously what Remy said does not apply. AND you have no crash (AV). However, Remy stated that (in the other cases) this can lead to undefined behavior. Which I read it something like: "it let's you access the method (which results in undefined behavior)" – Gabriel Apr 29 '19 at 07:41
  • 2
    I think this question is off topic, since it seems to be 'why did Remy say this'. You already got the answer to the actual question about using nil reference (here and in two other incarnations of your question), and if you want to ask clarification about a specific comment, please do so in another comment. Also, I know it's hard to believe, but even Remy could maybe have made a mistake, or have chosen some poor wording in his comment, so maybe it's unfair to discard the various answers your got in favor of this one comment. – GolezTrol Apr 29 '19 at 08:02
  • 1
    Remy is right. But in your question, it really depends on what you mean with **accessing**. If you mean **dereferencing**, then yes, it will cause an AV, or GPF or NilPointerException or whatever is appropriate on the platform. If you mean calling a method on a nil object, then it is not so clear. Then it depends on what that method does, if it is virtual/dynamic or not, etc. And since it is not clearly defined, it is called undefined behaviour. – Rudy Velthuis Apr 29 '19 at 09:47

1 Answers1

8

There is no guarantee that accessing nil pointer will raise an exception.

True.

However, the actual behavior depends on the actual code.

Exception will be raised if you call dynamic or virtual methods and when you try accessing the instance fields directly.

It is perfectly safe to call static method on nil reference and testing Self for nil inside it.

The best example of such static method is Free.

procedure TObject.Free;
begin
  if Self <> nil then
    Destroy;
end;

Obviously, above behavior is well defined, otherwise every Delphi program ever written would crash randomly (or all the time).


In general, accessing fields of nil reference will result in crash. In theory with large enough class anything is possible.

Example class provided by David Heffernan

type
   TSillyExample = class
     FStuff: array [0..SomeVeryLargeNumber-1] of Byte;
     FAreYouFeelingLucky: string;
   end;
Dalija Prasnikar
  • 27,212
  • 44
  • 82
  • 159
  • I agree with you about Free and I also agree with BrakNicku about Caption. However, I think that Remy was speaking about something else: "An exception might be raised, or you might just read garbage, or you might trash memory, or ... ". In case of Free, none of the above will happen. – Gabriel Apr 29 '19 at 07:48
  • 2
    What he said can happen when you access dangling pointer, when you access nil behavior is pretty much defined, but what the actual result will be depends on the code. – Dalija Prasnikar Apr 29 '19 at 07:50
  • I agree about dangling pointers. BUT he didn't mentioned a dangling pointer. He clearly said "there is no guarantee that accessing a NIL pointer will raise an exception". And then: "or you might just read garbage, or you might trash memory" – Gabriel Apr 29 '19 at 07:54
  • Obviously, I cannot speak for Remy and what he actually meant at the time... looking at your other question his comment makes sense even if not 100% correct. You asked whether you should return nil or raise an exception... comment was related to the assumption that if you return nil, any attempted usage of that reference will result in exception anyway, which is not true. – Dalija Prasnikar Apr 29 '19 at 08:06
  • 2
    Strictly speaking this is incorrect. The fields can perfectly well be located in valid memory. The fields start at an address close to 0. If the object is large enough, then the address of some fields may be accessible. – David Heffernan Apr 29 '19 at 09:26
  • @DavidHeffernan theoretically,yes. But, I have to admit, I haven't seen such example, yet. – Dalija Prasnikar Apr 29 '19 at 09:30
  • In any case, accessing nil reference by mistake and hoping for AV is not good programming practice. On LLVM based compilers, even if exception is raised, it can escape immediate exception handler. – Dalija Prasnikar Apr 29 '19 at 09:33
  • 1
    `type class = TSillyExample FStuff: array [0..SomeVeryLargeNumber-1] of Byte; FAreYouFeelingLucky: string; end;` But yes, in Windows at least, you have to work hard to get past the reserved area at the bottom of the virtual address space that extends to 0x0000ffff. – David Heffernan Apr 29 '19 at 09:47