无效指针操作

3
我有一个表单,其中包含一个名为TOpenDialog的组件(OpenDialog1)和一个按钮。 OpenDialog1Options属性中的ofAllowMultiSelect设置为true。
点击按钮后,将执行AddFilesToListView方法:
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;

运行应用程序时,选择第一个文件没有问题,但是当想要选择第二个文件时,会出现错误提示“Project project3 raised an exception class EInvalidPointer with message 'Invalid Pointer Operation'.”。这是什么原因造成的?如何纠正这个问题?
3个回答

23
“Invalid pointer operation” 意味着你释放了不属于你的内存。导致这种情况可能有以下三个原因:
  • 你的程序释放了已经被释放过一次的东西。
  • 你的程序释放了根本没有被分配的东西。
  • 你的程序释放了由其他内存管理器分配的东西。
在你的代码中,你正在释放 TOpenDialogFiles 属性。你没有分配该字符串列表,并且文档也没有告诉你要释放它,因此可以合理地认为该列表实际上属于对话框组件,并且当组件需要时将自动释放它。检查 Dialogs.pas 中的源代码可以证实这一点。由于你还释放了该对象,所以你有一个双重释放错误,符合我上面列出的第一个标准。请移除那一行。
正如Uwe 指出的那样,你也在处理文件名的 列表,但只检查了其中一个的存在性。这是你程序的逻辑错误,但不会导致你看到的异常。

你可能会因为一些不属于你的内存释放而导致无效指针操作异常。这只是意味着你遵循了一个错误的指针。释放别人的数据是其中之一,但并不是唯一的原因。 - Loren Pechtel
通常情况下,访问无效指针会导致EAccessViolation或混乱的数据,而不是EInvalidPointer。唯一的例外是,如果您以某种方式覆盖了编译器生成的TTypeInfo记录的Kind字段,则可能在Initialize或Finalize期间或在记录或数组分配期间失败。与“释放不属于您的内容”相同的类别是,在引用计数对象的引用计数为零之前释放该对象的情况。(搜索reInvalidPtr的源代码。) - Rob Kennedy

3
您应该检查以下内容:
if FileExists(OpenDialog1.Files[I]) then begin

替代

if FileExists(OpenDialog1.FileName) then begin

最好投资于一个本地变量来保存该值。

为什么这样做呢?

OpenDialog1.Files.Free;

嗨Uwe,我改成了'if FileExists(OpenDialog1.Files[I]) then begin',并注释掉了这行:OpenDialog1.Files.Free; 错误消失了。看来最后一行是引起问题的那一行。 - Attilah

2

Files是属于TOpenDialog的,不应直接释放。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接