views:

2148

answers:

3

I have a form that contains a TOpenDialog component (OpenDialog1) and a button. OpenDialog1 has the ofAllowMultiSelect (of Options) property set to true.

Upon clicking the button the method AddFilesToListView is executed:

procedure TForm4.AddFilesToListView();
var
  ListItem : TListItem;
  I: Integer;
  F : File;
  LengthOfAudio : TDateTime;
  previousCursor : TCursor;

begin
  previousCursor := Self.Cursor;
  Self.Cursor := crHourGlass;

  if OpenDialog1.Execute then
  begin
    for I := 0 to OpenDialog1.Files.Count - 1 do begin
      if FileExists(OpenDialog1.FileName) then begin
        ListItem:=ListView1.Items.Add;
        ListItem.Caption := 'Test';
        ListItem.SubItems.Add(ExtractFileName(OpenDialog1.Files[I]));
        ListItem.SubItems.Add(ExtractFilePath(OpenDialog1.Files[I]));
      end else
        raise Exception.Create('File does not exist.');
    end;
  end;

  Self.Cursor := previousCursor;

  OpenDialog1.Files.Free;
end;

When running the application, selecting the first file, I have no problem but when wanting to select the second one, I get an error saying "Project project3 raised an exception class EInvalidPointer with message 'Invalid Pointer Operation'."

What's the cause of this, how do I correct this?

+3  A: 

You should check for

if FileExists(OpenDialog1.Files[I]) then begin

instead of

if FileExists(OpenDialog1.FileName) then begin

Better invest in a local variable holding that value.

And why this?

OpenDialog1.Files.Free;
Uwe Raabe
Hi Uwe, I changed to 'if FileExists(OpenDialog1.Files[I]) then begin ' and I commented out this line : OpenDialog1.Files.Free;and the error disappeared. it seems the last line was the one causing the problem.
Attilah
+4  A: 

"Invalid pointer operation" means you freed memory that didn't belong to you. One of these three things is the cause:

  • Your program freed something that had already been freed once before.
  • Your program freed something that was never allocated in the first place.
  • Your program freed something that had been allocated with a different memory manager.

In your code, you're freeing the TOpenDialog's Files property. You didn't allocate that string list, and the documentation doesn't tell you to free it, so it's reasonable to expect that the list actually belongs to the dialog component, and that the component will free it when it wants. Checking the source code in Dialogs.pas confirms that. Since you have also freed that object, you have a double-free error, which meets the first criterion I listed above. Remove that line.

As Uwe pointed out, you're also processing a list of file names but only checking the existence of one. That's a logic error in your program, but it would not cause the exception you're seeing.

Rob Kennedy
You can get Invalid Pointer Operation exceptions from things other than freeing memory that didn't belong to you. It simply means you followed a bad pointer. Freeing someone else's data is one cause of it, not the only cause of it.
Loren Pechtel
Following a bad pointer generally gets you EAccessViolation or garbled data, not EInvalidPointer. The exception to that is if you somehow overwrite the Kind field of a compiler-generated TTypeInfo record, in which case you may get a failure in Initialize or Finalize, or during assignment of records or arrays. In the same category as "freeing something that's not yours" is the case where you free a reference-counted object before its reference count is zero. (Search the source code for reInvalidPtr.)
Rob Kennedy
+2  A: 

Files is owned by the the TOpenDialog, and should not be freed directly.

skamradt