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在没有无效指针操作的情况下工作,但是在退出我的应用程序时出现内存泄漏。
答案 0 :(得分:3)
主要问题在于:
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;