2011-08-16 53 views
3

我有以下代码(我查objCur是不是免费前无}:这个无效指针在哪里?

try 
    objCur.Free; 
Except on E:Exception do 
    begin 
    OutputDebugString(PChar('Exception '+E.Message)); 
    Assert(False); 
    end; 
end; 

据报告此异常消息:

无效的指针操作objCur是TXX_TEA型
objCur:TXX_TEA ;

在TXX_TEA.Destroy我有以下代码

destructor TXX_TEA.Destroy; 
begin 
    OutputDebugString(PChar('Inside Destroy')); 
    ... 
    inherited; 
    OutputDebugString(PChar('End of Destroy')); 
end; 

在DebugView中我看到以下消息:

内摧毁
...
最终的销毁

异常:无效的指针操作

我知道objCur.Free电话TXX_TEA.Destroy,但它看起来TXX_TEA.Destroy无误地执行。那么我应该在哪里跟踪这个无效的指针操作?

+3

检查'objCur'是否为非零是不够的。事实上,如果它*为零,你根本就没有任何问题。你需要检查它是否指向一个有效的对象,这实际上不是你可以通过编程来检查的东西。您需要通过分析程序来检查并确保您没有任何会导致变量具有无效参考的错误。 –

+0

Acutally我想知道什么时候objCur.Free,它会先调用TXX_TEA.Destroy,然后它将释放它自身的属性?因为在TXX_TEA中,有一个属性Allos,Allos [i] .xx = self.xx;在TXX_TEA.Destroy中,调用Allos.Free。所以我怀疑当objCur释放它的xx属性时,它已经被释放了 – spspli

回答

9

当内存管理器被要求释放不属于它的内存时,会发生无效的指针操作。

对象的内存在最外面的析构函数返回给调用者之前被释放。在这种情况下的来电者是TObject.Free。调用inherited不会导致释放对象的内存,因为编译器知道它不是最外层的调用。显然,你释放了一个并不存在的对象,但是这个假定对象的内存内容看起来足够有效,以至于清理对象字段的析构函数中的代码不会崩溃。只有当析构函数完成运行并且对象将被释放时,内存管理器才会检测到该地址没有引用当前分配的任何内容。

3

很可能您仍然有一个对它的引用,并且某些代码在释放后使用该引用来访问该对象。这可以是一个对象引用或接口引用(接口引用不为零将在范围末尾调用_Release)。

我们必须看到更多代码才能真正找出导致它的原因。

+0

+1接口引用计数 –

+0

那么是否有一个通用的方法来找出对象引用或接口引用的位置? – spspli

+1

使用RTL和VCL调试单元进行调试将帮助您了解实际发生的情况,以及可能出现的问题。在引发异常之前,还要查看堆栈跟踪*。 –

6

一个无效的指针当你试图释放某些东西时的操作几乎总是意味着它已经被释放。如果你想找到哪里,最简单的方法是从SourceForge获取完整版本的FastMM。阅读文档,它会告诉你如何将它添加到你的项目以及如何打开FullDebugMode。在FullDebugMode打开的情况下,当你试图释放已经释放的东西时,它会通过一个对话框中断程序,该对话框为您提供了第一次释放对象时的堆栈跟踪。这应该有助于您追踪错误。