Pascal Dispose导致分段错误,但我不明白为什么

时间:2016-07-31 14:49:05

标签: class pointers segmentation-fault runtime-error delphi

program Project1;

type
  ob = class
    num: integer;
    constructor init(id: integer);
    destructor done();
  end;

  constructor ob.init(id: integer);
  begin
    self.num := id;
  end;

  destructor ob.done();
  begin
  end;

type
  plist = ^list;

  list = record
    myob: ^ob;
    Next: plist;
  end;
var start:plist;
begin

  start:=nil;
  new(start);
  start^.myob^:=ob.init(1);
  new(start^.next);
  start^.Next^.myob^:=ob.init(2);
  start^.next^.myob^.done();
  dispose(start^.Next);
  start^.myob^.done();
  dispose(start);

end.

此代码导致 错误:项目project1引发了异常类'外部:SIGSEGV'。地址405B32

当我尝试在调试中运行时,我会弹出汇编程序屏幕并显示

SYSTEM_$$_SYSGETMEM$LONGWORD$$POINTER(147)
00405B23 b890e44000               mov    $0x40e490,%eax
00405B28 e813080000               call   0x406340 <SYSTEM_$$_ENTERCRITICALSECTION$TRTLCRITICALSECTION>
00405B2D 89d8                     mov    %ebx,%eax
00405B2F 8b5004                   mov    0x4(%eax),%edx    <-error here
00405B32 8b92a0000000             mov    0xa0(%edx),%edx   <-or it might be here
00405B38 89500c                   mov    %edx,0xc(%eax)
00405B3B 8b5004                   mov    0x4(%eax),%edx
00405B3E 8982a0000000             mov    %eax,0xa0(%edx)
00405B44 b890e44000               mov    $0x40e490,%eax
00405B49 e802080000               call   0x406350 <SYSTEM_$$_LEAVECRITICALSECTION$TRTLCRITICALSECTION>

任何帮助将不胜感激

我如何解决此问题似乎只有在我尝试使用dispose时才会发生 提前谢谢你

1 个答案:

答案 0 :(得分:0)

首先,您不应该使用类实例(a.k.a.对象)的指针。类实例已经是引用类型:

plist = ^list;
list = record
  myob: ob;
  next: plist;
end;

现在你可以做到:

start^.myob := ob.init(1);
...
start^.next^.myob := ob.init(2);

你不会再崩溃了。

现在有些评论

这不是强制性的,但通常使用Create作为构造函数的名称。析构函数通常称为Destroy,应该是覆盖(虚拟TObject.Destroy):

ob = class
  num: Integer;
  constructor Create(id: Integer);
  destructor Destroy; override;
end;

此外,通常最好在构造函数中调用继承的构造函数,并在析构函数中调用继承的析构函数。即使你的类(隐含地)直接来自TObject,在一个不那么简单的程序中也可能不是这种情况。

最后,从不直接调用析构函数是一个好习惯。请改用Free(这预先假定您的析构函数为override并称为Destroy)。这首先检查Selfnil,这对于存储在其他类中的类实例是有好处的(如果外部类构造函数失败,那么当外部类'析构函数时,某些包含的类可能尚未初始化)被称为。)