Delphi - TObjectDictionary 在免费时给出无效指针

标签 delphi

Delphi XE6 - 我正在使用 TObjectDictionary 和自定义类。我创建、添加,然后免费。只要我这样做,一切就都很好。如果我执行“TryGetValue”,我会收到“无效指针操作”。 TryGetValue 工作正常,给出了正确的结果,但稍后会导致问题......

这是我的代码。

 type
  TWordRec = class
  public
    RemoveAlways: Boolean; // Is this CORP LLC, etc?
    RemoveRestricted: Boolean;
    Replace: Boolean;
    ReplaceWith: string;
    Constructor Create(B1, B2, B3: Boolean; S1: String); overload;
  end;
...
constructor TWordRec.Create(B1, B2, B3: Boolean; S1: String);
begin
  self.RemoveAlways := B1; // Is this CORP LLC, etc?
  self.RemoveRestricted := B2;
  self.Replace := B3;
  self.ReplaceWith := S1;
end;

我在按钮上添加测试代码...

procedure TForm1.Button1Click(Sender: TObject);
var
CurrentDictEntry : TWordRec;
FoundIt : Boolean;

begin

ReportMemoryLeaksOnShutdown := True;

WordDict := TObjectDictionary<String, TWordRec>.Create([doOwnsValues]);
WordDict.Add('CO', TWordRec.Create(True, False, False, ''));
WordDict.Add('CORP', TWordRec.Create(True, False, False, ''));
WordDict.Add('CORPORATION', TWordRec.Create(True, False, False, ''));

CurrentDictEntry := TWordRec.Create(False, False, False, '');

// If I remove next two code lines, everything is fine
// With these 2 lines, I get error ON WordDict.Free;
FoundIt := WordDict.TryGetValue('CORP', CurrentDictEntry);
if FoundIt = True then ShowMessage('Found');

CurrentDictEntry.Free;
WordDict.Free;
end;

为什么我无法释放我的 WordDict?如果我只是释放 WordDict(即注释掉 CurrentDictEntry.free),则 WordDict.Free 可以在没有无效指针操作的情况下工作,但退出应用程序时会出现内存泄漏。

最佳答案

主要问题在这里:

CurrentDictEntry.Free;

此时,CurrentDictEntry 是包含在容器中的值。并且您无法释放此容器中的值,因为容器拥有它们。如果您尝试释放值,那么容器稍后将尝试再次释放它们,这是典型的双重释放问题。

一旦你告诉容器拥有这些值,你就不能释放它们。

另一个问题是您泄漏了 TWordRec

CurrentDictEntry := TWordRec.Create(False, False, False, '');
FoundIt := WordDict.TryGetValue('CORP', CurrentDictEntry);

第一行创建一个新对象并在 CurrentDictEntry 中保存对其的引用。然后,第二行覆盖 CurrentDictEntry,现在您根本没有对刚刚创建的对象的引用,因此它被泄漏。

您的代码应如下所示:

ReportMemoryLeaksOnShutdown := True;

WordDict := TObjectDictionary<String, TWordRec>.Create([doOwnsValues]);
try
  WordDict.Add('CO', TWordRec.Create(True, False, False, ''));
  WordDict.Add('CORP', TWordRec.Create(True, False, False, ''));
  WordDict.Add('CORPORATION', TWordRec.Create(True, False, False, ''));

  FoundIt := WordDict.TryGetValue('CORP', CurrentDictEntry);
  if FoundIt then 
    ShowMessage('Found');
finally
  WordDict.Free;
end;

关于Delphi - TObjectDictionary 在免费时给出无效指针,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25645077/

相关文章:

windows - 如何获取 NtQueryInformationProcess 所需的缓冲区大小?

delphi - 是否可以将FileAge设置为毫秒?

delphi - 我想禁用 JEDI 字符串属性编辑器

delphi - 如何使用TTaskDialog?

windows - 可以覆盖 CreateParams 过程让我仍然可以完全访问 WS_SYSMENU 吗?

delphi - JSON 解析器的要求

function - Delphi SAP SAPFunctions DELIMITER 突然被忽略?

delphi - 如何释放嵌套(对象类型)字段类?

delphi - Delphi 的匿名方法中引用的变量如何以及何时被捕获?

delphi - 如何获得指针指向的浮点值?