Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/delphi/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Delphi 内存泄漏与访问冲突、类设计问题_Delphi_Memory Leaks - Fatal编程技术网

Delphi 内存泄漏与访问冲突、类设计问题

Delphi 内存泄漏与访问冲突、类设计问题,delphi,memory-leaks,Delphi,Memory Leaks,我在下面的代码中展示了一个用户类的简短设计模式 type MytestClass = class alist: TStringlist; public constructor Create; destructor destroy; override; end; { MytestClass } type TForm1 = class(TForm) btn_version01: TBitBtn; btnversion02: TBitBtn

我在下面的代码中展示了一个用户类的简短设计模式

type
  MytestClass = class
    alist: TStringlist;
  public
    constructor Create;
    destructor destroy; override;
  end;
  { MytestClass }

type
  TForm1 = class(TForm)
    btn_version01: TBitBtn;
    btnversion02: TBitBtn;
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
    procedure FormCreate(Sender: TObject);
    procedure btn_version01Click(Sender: TObject);
    procedure btnversion02Click(Sender: TObject);
  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }

    btestClass : MytestClass;
    aComplexClassDesign : TComplexClassDesign;
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

constructor MytestClass.Create;
begin
  alist := TStringlist.Create;
end;

destructor MytestClass.destroy;
begin
  alist.free;
  inherited;
end;


procedure TForm1.btnversion02Click(Sender: TObject);
var atestClass : MytestClass;
begin
     ///
  atestClass :=MytestClass.Create;
  atestClass.Free;
  atestClass := nil;
end;

procedure TForm1.btn_version01Click(Sender: TObject);
var atestClass : MytestClass;
begin
     ///
  atestClass :=MytestClass.Create;
  atestClass.Free;
end;

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  btestClass.free;
  aComplexClassDesign.Free;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  btestClass :=MytestClass.Create;
  aComplexClassDesign :=TComplexClassDesign.Create;
end;

end.
希望这是一个完美的设计,没有内存泄漏和访问冲突。我在实际应用程序中使用的所有类都是按照这种模式设计的

在上面的代码中,FastMM4在我的TComplexClassDesign上没有显示任何问题。在实际应用程序中,FASTMM4正在报告我的TComplexClassDesign的内存泄漏,甚至我在窗体的关闭事件中调用了free函数。如果我一步一步地检查代码,确保该函数已执行。 您知道如何调试此内存泄漏报告吗?您知道如何查看尚未发布的TComplexClassDesign实例吗?我收到这个奇怪的内存泄漏报告还有其他原因吗

奖金问题:

DUnit总是这样编写拆卸代码

  atestClass :=MytestClass.Create;
  atestClass.Free;
  atestClass := Nil
是否真的需要最后一行代码?

额外答案:

即使调用了free,atestClass仍将指向内存地址。如果在调用free后尝试访问内存,则如果其他内容正在使用该内存位置,则可能访问错误的数据;如果内存不再可访问,则可能会导致访问冲突

如果free是函数中的最后一行,然后它退出/返回,则可能不需要它

奖励答案:

即使调用了free,atestClass仍将指向内存地址。如果在调用free后尝试访问内存,则如果其他内容正在使用该内存位置,则可能访问错误的数据;如果内存不再可访问,则可能会导致访问冲突


如果free是函数中的最后一行,然后它退出/返回,则可能不需要它

OnCreate
OnClose
匹配是错误的。这些事件不是一对。在构造过程中调用
OnCreate
事件。销毁的匹配事件是
OnDestroy
。在
OnCreate
中创建的任何内容都应在
OnDestroy
中销毁

我个人认为,
OnCreate
onestroy
没有什么价值。我总是选择重写虚拟构造函数和析构函数


一般来说,按与创建相反的顺序销毁对象。这在这里并不重要,但是如果对象具有依赖关系,那么顺序有时很重要


nil
分配给
atestClass
有什么意义吗?绝对不是。该变量在赋值后立即离开作用域,因此任何其他代码都无法观察结果赋值。我希望编译器对此发出警告。当您进行赋值时会发出警告,但决不使用赋值。我希望您已启用警告



最后,为什么您的真实代码存在内存泄漏?从这里看不出来。FastMM的完整调试版本提供带有信息堆栈跟踪的泄漏报告。这些跟踪将包括导致泄漏对象分配的调用堆栈

OnCreate
OnClose
匹配是错误的。这些事件不是一对。在构造过程中调用
OnCreate
事件。销毁的匹配事件是
OnDestroy
。在
OnCreate
中创建的任何内容都应在
OnDestroy
中销毁

我个人认为,
OnCreate
onestroy
没有什么价值。我总是选择重写虚拟构造函数和析构函数


一般来说,按与创建相反的顺序销毁对象。这在这里并不重要,但是如果对象具有依赖关系,那么顺序有时很重要


nil
分配给
atestClass
有什么意义吗?绝对不是。该变量在赋值后立即离开作用域,因此任何其他代码都无法观察结果赋值。我希望编译器对此发出警告。当您进行赋值时会发出警告,但决不使用赋值。我希望您已启用警告



最后,为什么您的真实代码存在内存泄漏?从这里看不出来。FastMM的完整调试版本提供带有信息堆栈跟踪的泄漏报告。这些跟踪将包括导致泄漏对象分配的调用堆栈

>最后一行代码真的需要吗?
。不,不需要。如果要重用变量
atestClass
,最好将其置零,否则就不行了。不过多年来一直在讨论这个问题,因为在某些情况下,它可以简化调试。搜索
FreeAndNil()
<代码>>真的需要最后一行代码吗?。不,不需要。如果要重用变量
atestClass
,最好将其置零,否则就不行了。不过多年来一直在讨论这个问题,因为在某些情况下,它可以简化调试。搜索
FreeAndNil()
。哈哈-当你只需要回答奖金问题的时候,为什么还要为实际问题写一个详细的答案呢。是的,我不知道为什么我的答案被标记为接受答案。很明显,我没有回答主要问题,也没有声称我是。我明确表示,我试图回答奖金问题。至于反对票或赞成票,我没有参与其中任何部分。因为社区不喜欢我的答案被接受,所以被否决是很奇怪的。是的,这不是主要问题的正确答案,但这可以通过修正已被接受的答案来解决。哈哈-既然你只需要回答奖金问题,为什么还要为实际问题写一个详细的答案呢。是的,我不知道为什么我的答案被标记为已被接受的答案。很明显,我没有回答主要问题,也没有声称我是。我显然是
procedure TForm1.FormCreate(Sender: TObject);
begin
  btestClass :=MytestClass.Create;
  aComplexClassDesign :=TComplexClassDesign.Create;
end;

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  btestClass.free;
  aComplexClassDesign.Free;
end;
procedure TForm1.btnversion02Click(Sender: TObject);
var atestClass : MytestClass;
begin
  atestClass :=MytestClass.Create;
  atestClass.Free;
  atestClass := nil;
end;