2012-04-11 113 views
8

我似乎无法找出这一个。我的程序编译并运行成功,但在调试期间,只有在关闭程序时弹出一个消息框,提示“无效的指针操作”。我精心检查了所有FormCloseQuery和FormDestory事件,以查找任何语法或逻辑错误。我没有发现,他们按预期执行没有任何错误。无效指针操作 - 德尔福XE

enter image description here

当我告诉编译器在无效指针操作错误打破,它不会做任何事情,但挂断程序。在这一点上,我不得不终止或杀死这个过程。

你如何看出这一点?

由于提前,

+6

启用调试DCU并逐步关闭,直到找到触发此错误的内容。您是否在Full Debug模式下运行FastMM? – 2012-04-11 20:09:34

+0

@DavidHeffernan,:)我记得我们有一个关于FastMM的对话。不幸的是,我还没有使用FastMM,因为我在测试时会跑回去。我将启用DCU并查看会发生什么。 – ThN 2012-04-11 20:16:54

+0

@DavidHeffernan,在启用了dcu之后,调试器停止在System.pas文件中。有点混乱,但我认为它是因为梅森惠勒的原因之一。我想现在我必须把FastMM放回去。 – ThN 2012-04-12 12:30:17

回答

25

无效指针异常是由内存管理器抛出的时候,它会释放无效的内存。有三种方式可以发生。

最常见的是因为您试图释放已释放的对象。如果打开FastMM的FullDebugMode,它会检测到这一点并直接指出问题所在。 (但是一定要建立一个地图文件,这样它就可以得到所需要的信息来创建有用的堆栈跟踪。)

第二种方法是,如果您试图释放分配给内存管理器以外的内存。在将DELPHI EXE中的字符串传递给未使用共享内存管理器功能的Delphi DLL时,我已经看到过这几次。

而第三种方式是直接用指针搞乱并可能不适用于你。如果您尝试使用FreeMemDispose一个不指向FastMM分配的实际内存块的错误指针,则会出现此错误。

这很可能是第一个。使用FullDebugMode,您可以轻松找到问题的根源。

+0

你是绝对正确的。你的第一个原因是为什么我的程序正在提出这个异常通知。然而,它正在升高,因为我的TForm的摧毁事件被称为不止一次。我不明白为什么。 – ThN 2012-04-12 15:10:10

+0

如果我要猜测,我会说因为您的表单是由一个所有者创建的(例如Application;您是否使用'Application.CreateForm'来构造它?),然后在其他地方尝试释放它手动。看看它被释放的两次堆栈轨迹;他们会给你一个想法是怎么回事。记住[单一所有权原则](http://tech.turbu-rpg.com/106/delphi-memory-management-made-simple):您的表单可以由应用程序或您的代码拥有,但不是两者都有。 – 2012-04-12 16:19:08

0

在Delphi调试过程中,我被这种“指示错误”所捕获。

检查,如果你有,尝试表明,可能未初始化在同一单位(或全球)其他变量启用“允许函数调用”或手表任何观看变量。在停止断点时,可能会导致Delphi的调试器尝试通过访问未初始化的指针或变量的函数调用来显示该值。导致AV的实际变量我甚至不在您的监视列表中。当你告诉德尔福内存管理器来释放不属于它的内存出现

+3

EAccessViolation与EInvalidPointer不同。 *访问*无效指针给前者;只有*释放*给后者。 – 2013-01-18 15:35:07

9

无效的指针操作。有三种方式可能发生:

  • 释放已被释放的指针或对象。
  • 使用FreeMem释放某些其他内存管理器分配的内容(如GlobalAllocCoTaskMemAlloc)。
  • 释放未初始化的指针。 (这与释放空指针截然不同,这是完全安全的。)

在程序的某个地方,您正在执行这些操作之一。调试器检测到内存管理器抛出的异常,所以做一些调试。从堆栈跟踪中,你应该能够看到你试图释放哪个变量。检查你的程序的其余部分是否使用了该变量的其他方式。

像MadExcept和Eureka Log这样的工具可以帮助您找到双免费错误。他们可以跟踪问题指针的分配位置以及第一次释放的位置,这有时可以帮助您找出错误并停止多次释放事件。

+0

如果尝试释放本地声明的对象的地址,是否也会抛出它? – Wolf 2015-01-13 09:17:49

+0

是的,@狼。这是第二个要点。在这种情况下,你会试图释放分配给堆栈的内存。 – 2015-01-13 13:18:45

+0

谢谢。这个“分配”或“内存管理器”在讨论自动变量时看起来很奇怪。也许这应该被添加(以更明确的方式)? – Wolf 2015-01-13 13:22:15

1

第四个原因是指针操作无效。我有两个指针,其中真正的数组[0..1000]和第三个指针是真实数组[1..200]。所有3个指针在初始化为 (对于i:= 0到1000) 开始 ptr1^[i]:= 0; ptr2^[i]:= 0; ptr3^[i]:= 0; 结束; 虽然这个糟糕的编程没有打扰Delphi中的Pascal,但是调用Dispose这3个指针中的任何一个导致无效指针操作。该修复只是为了正确初始化第三个指针。