如何追踪访问冲突"地址00000000"

Obi*_*obi 29 delphi

我知道如何创建一个.map文件来跟踪错误消息包含实际地址时的访问冲突错误.

但是,如果错误消息说明了什么

Access violation at address 00000000. Read of address 00000000.
Run Code Online (Sandbox Code Playgroud)

我从哪里开始寻找这个问题的原因......?

Hea*_*utt 32

接受的答案并不能说明整个故事.

是的,无论何时看到零,NULL都会涉及指针.这是因为NULL通过定义为零.所以叫零NULL可能不是很多.

什么你得到的消息有趣的是,其实NULL提到两次.实际上,您报告的消息看起来有点像Windows品牌操作系统向用户显示的消息.

消息说地址 NULL试图阅读 NULL.那是什么意思呢?具体来说,地址如何自行读取?

我们通常会考虑在某个地址读取和写入内存的地址处的指令.知道这允许我们解析错误消息.该消息试图阐明地址处的指令试图阅读. NULL NULL

当然,地址上没有指令NULL,这就是我们NULL在代码中认为特殊的原因.但是,每一条指令都可以被认为是从阅读本身的尝试开始.如果CPU EIP寄存器位于地址NULL,则CPU将尝试 从地址0x00000000()读取操作码以获取指令NULL.此尝试尝试NULL将失败,并生成您收到的消息.

在调试器中,EIP当您收到此消息时,请注意等于0x00000000.这证实了我给你的描述.

接下来的问题是,"为什么我的程序会尝试执行NULL地址." 我想到了三种可能性:

  • 您已尝试通过已声明,已分配NULL,从未初始化的函数指针进行函数调用,并且正在取消引用.
  • 类似地,您可能正在调用一个"抽象"C++方法,该方法NULL在对象的vtable中有一个条目.这些是使用语法在代码中创建的virtual function_name()=0.
  • 在您的代码中,堆栈缓冲区在写入零时溢出.在保留的返回地址上写入超出堆栈缓冲区末尾的零.当函数稍后执行其ret指令时,NULL将从覆盖的内存点加载值0x00000000().这种类型的错误,堆栈溢出,是我们论坛的同名词.

既然你提到你正在调用第三方库,我将指出库可能是一种情况,期望你提供一个非NULL函数指针作为某些API的输入.这些有时被称为"回叫"功能.

您将不得不使用调试器来进一步缩小问题的原因,但上述可能性应该可以帮助您解决问题.


Ken*_*ite 29

地址'00000000'附近任何地方的访问冲突都表示空指针访问.你在创建它之前使用的东西很可能,或者在它被FreeAndNil()之后.

很多时候,这是由于在表单创建过程中访问错误位置的组件,或者让主表单尝试访问尚未创建的数据模块中的某些内容而导致的.

MadExcept可以很容易地跟踪这些内容,并且可以免费用于非商业用途.(实际上,商业使用许可证也很便宜,非常物有所值.)

  • 我将此标记为"正确"响应,因为有关MadExcept的提示非常有用.但是,在我的具体情况下,似乎错误发生在第三方库中(并且可以通过应用供应商补丁来修复),所以这次我不需要进一步研究. (4认同)

Rob*_*edy 7

你开始寻找你知道运行的代码附近,并且当你到达你知道没有运行的代码时就停止查找.

您正在寻找的可能是程序通过函数指针调用函数的某个地方,但该指针为空.

你也可能有堆栈损坏.您可能已将函数的返回地址覆盖为零,并且异常发生在函数的末尾.检查可能的缓冲区溢出,如果要调用任何DLL函数,请确保使用正确的调用约定和参数计数.

这不是使用空指针的常见情况,如未分配的对象引用或PChar.在这些情况下,您将具有非零"地址x "值.由于指令发生在地址0,因此您知道CPU的指令指针未指向任何有效指令.这就是为什么调试器不能告诉你哪行代码导致的问题-有没有行的代码.您需要通过查找指向CPU跳转到无效地址的位置的代码来找到它.

调用堆栈可能仍然完好无损,这至少应该让您非常接近目标.但是,如果您有堆栈损坏,则可能无法信任调用堆栈.