我问这个问题是因为我没有好主意......希望得到别人的新观点。
我有一个用户在 Windows 7 64 位系统上运行我们的 32 位 Delphi 应用程序(使用 BDS 2006 编译)。直到几周前,我们的软件都“运行良好”。现在突然不是这样了:它在初始化(实例化对象)时抛出访问冲突。
我们让他重新安装了我们所有的软件——从头开始。同样的 AV 错误。我们禁用了他的防病毒软件;同样的错误。
出于某种原因,我们的堆栈跟踪代码 ( madExcept ) 无法提供错误行的堆栈跟踪,因此我们发送了几个错误日志记录版本供用户安装和运行,以隔离产生错误的行...
事实证明,这是一个实例化一个简单的 TStringList 后代的行(没有重写的 Create 构造函数等 - 基本上 Create 只是实例化一个 TStringList,它有一些与后代类关联的自定义方法。)
我很想向用户发送另一个测试 .EXE;它只是实例化一个普通的 TStringList,看看会发生什么。但在这一点上,我感觉自己就像在风车上猛烈地挥舞,如果我发送太多“要尝试的东西”,就有可能耗尽用户的耐心。
关于调试该用户问题的更好方法有什么新想法吗? (我不喜欢解决用户的问题……这些问题往往如果被忽视,就会突然成为其他 5 个用户突然“发现”的流行病。)
按照 Lasse 的要求进行编辑:
procedure T_fmMain.AfterConstruction;
begin
inherited;
//Logging shows that we return from the Inherited call above,
//then AV in the following line...
FActionList := TAActionList.Create;
...other code here...
end;
这是正在创建的对象的定义...
type
TAActionList = class(TStringList)
private
FShadowList: TStringList; //UPPERCASE shadow list
FIsDataLoaded : boolean;
public
procedure AfterConstruction; override;
procedure BeforeDestruction; override;
procedure DataLoaded;
function Add(const S: string): Integer; override;
procedure Delete(Index : integer); override;
function IndexOf(const S : string) : Integer; override;
end;
implementation
procedure TAActionList.AfterConstruction;
begin
Sorted := False; //until we're done loading
FShadowList := TStringList.Create;
end;
最佳答案
我讨厌这类问题,但我认为你应该在对象尝试构造之前关注最近发生的事情。
您描述的症状听起来像典型的堆损坏,所以也许您有类似的情况......
- 数组被写入外部边界? (如果关闭了边界检查,请打开它)
- 代码试图访问已删除的对象?
自从我上面回答以来,您已经发布了代码片段。我认为这确实引发了一些可能的问题。
a:AfterConstruction 与修改后的构造函数: 正如其他人所提到的,以这种方式使用 AfterConstruction 充其量不是惯用的。我不认为这真的是“错误”,但它可能是一种气味。 Dr. Bob's site here. 对这些方法有很好的介绍。
b:重写方法Add、Delete、IndexOf 我猜测这些方法以某种方式使用 FshadowList 项。在创建 FShadowList 之前是否有可能调用这些方法(从而使用 FShadowList)?这似乎是可能的,因为您正在使用上面的 AfterConstruction 方法,此时虚拟方法应该“起作用”。希望通过设置一些断点并查看它们被击中的顺序,可以使用调试器轻松检查这一点。
关于delphi - 如何调试(可能的)RTL 问题?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5998279/