title: Disposing pointers to complex records
body: <p>I have list of pointers to some complex records. Sometimes when I try disposing them I get invalid pointer operation error. I'm not really sure if I'm creating and disposing them properly.
  The record looks like this:</p>
  
  <pre><code>type
    PFILEDATA = ^TFILEDATA;
    TFILEDATA = record
      Description80: TFileType80;  // that's array[0..80] of WideChar
      pFullPath: PVeryLongPath;    // this is pointer to array of WideChar
      pNext: PFILEDATA;            // this is pointer to the next TFILEDATA record
    end;
  </code></pre>
  
  <p>As I understand when I want a pointer to such record I need to initialize the pointer and the dynamic arrays like this:</p>
  
  <pre><code>function GimmeNewData(): PFILEDATA;
  begin
    New(Result);
    New(Result^.pFullPath);
  end;
  </code></pre>
  
  <p>Now to dispose of series of these records I wrote this:</p>
  
  <pre><code>procedure DisposeData(var pData: PFILEDATA);
  var pNextData: PFILEDATA;
  begin
    while pData^.pNext &lt;&gt; nil do begin
      pNextData := pData^.pNext;          // Save pointer to the next record
      Finalize(pData^.pFullPath);         // Free dynamic array
      Dispose(pData);                     // Free the record
      pData := pNextData;
    end;
    Finalize(pData^.pFullPath);
    Dispose(pData);
    pData := nil;
  end;
  </code></pre>
  
  <p>When I run my program in the debug mode (F9) in the Delphi 2010 IDE something weird happens. When I step trough DisposeData code with F8 it appears that program skips Finalize(pData^.pFullPath) line and jumps to Dispose(pData). Is this normal? Also when Dispose(pData) is executed the Local variables window that displays contents of the pointers does not change. Does this mean that dispose fails?</p>
  
  <p>Edit:
  PVeryLongPath is:</p>
  
  <pre><code>type
    TVeryLongPath = array of WideChar;
    PVeryLongPath = ^TVeryLongPath;
  </code></pre>
  
  <p>Edit2</p>
  
  <p>So I create 2 TFILEDATA records then I dispose them. Then I create the same 2 records again. For some reason this time pNext in the second record is not nil. It points to the 1st record. Disposing this weird thing gets invalid pointer operation error.
  Randomly I have inserted pData^.pNext := nil in the DisposeData procedure.
  Now the code looks like this:</p>
  
  <pre><code>procedure DisposeData(var pData: PFILEDATA);
  var pNextData: PFILEDATA;
  begin
    while pData &lt;&gt; nil do begin
      pNextData := pData^.pNext;
      pData^.pNext := nil;          // &lt;----
      Dispose(pData^.pFullPath);
      Dispose(pData);
      pData := pNextData;
    end;
  end;
  </code></pre>
  
  <p>The error is gone.
  I'll try to change PVeryLongPath into TVeryLongPath.</p>