是否可以检查内存地址是否有效?



一个客户带着一个丢失了源代码的应用程序来找我。这个应用程序似乎是随机崩溃,当加载一些文件。我怀疑这个问题是由于一个竞争条件,其中指针被删除,然后要么不设置为NULL,要么不检查有效性。

当使用OllyDBG逐步执行程序集时,我发现崩溃总是发生在同一位置,所以这是一种强化我的理论。这是它有时崩溃的装配线,有时是关键字。

MOV EDI,DWORD PTR DS:[EAX]

是否有可能通过本机汇编或通过内联汇编调用(或类似的东西)拉出地址的c++来验证内存地址是否有效并存在?

在c++中没有通用的标准方法来验证内存地址。据我所知,也没有这样的汇编指令。

在内存映射系统(如任何现代操作系统)上,您可以使用系统特定的API检查是否已为进程映射了地址。映射到进程的地址不能保证该地址是有效的从c++的角度来看,但是一个未映射的地址肯定是无效的。

此外,即使if可以发现一个地址是有效的,也不能告诉你所期望的对象是在这个地址中还是在其他地方。


在c++语言1之外有验证内存访问的工具。比如Valgrind,编译器也提供地址消毒和内存消毒。大多数情况下,这有助于检测无效访问,否则不会使程序崩溃。但是它们通常也可以提供关于内存的额外信息。

1如果你有访问源代码的权限。

我怀疑这个问题是由于竞争条件

能够验证内存地址并不能解决这个问题。你应该做的是1,是使用调试器来找出正在被访问的对象,找到该对象被访问的所有位置。如果这些地方中的任何一个没有持有一个互斥锁,而这个互斥锁对于所有其他可能同时访问该对象的地方都是通用的,那么这就是你的bug。

1如果你有访问源代码的权限。

丢失源代码

如果你有大量的预算,那么你可以尝试逆向工程,并试图弄清楚它在做什么。我不会屏住呼吸;也许最好宣布这是注定要失败的。

每个人都提供了一些很棒的回复。不幸的是,在这种情况下,客户不愿意花钱重新开发整个软件。

我设法消除了崩溃…在确定了崩溃发生的确切位置之后,我将代码注入到JMP到一个自定义的c++函数。c++函数使用了__try __except块。在Try中,我放置了问题汇编代码,如果问题代码导致崩溃,__except会捕获它。在那之后,就只需要分析问题代码在做什么,什么时候开始做其他事情,然后跳转到"其他事情"的开始。捕获异常时问题函数的一部分。

它不是准确地检测内存位置是否有效,而是如果它导致异常,它只是跳过代码。希望这篇文章最终能帮助到一些人…

是的,验证指针的内容是可能的。然而,验证目标是否正确就比较困难了。

为了验证一个指针,你需要:

  1. 有效地址范围表(已实现的地址及其范围)。
    例如,在嵌入式系统上,被解码的地址可能不是在所有位置都有内存或设备。
  2. 对于支持分页或虚拟内存的操作系统,您需要计算出程序内存区域的限制(由操作系统给出)。操作系统可能会把你的部分可执行文件和硬盘上的代码交换出来。
  3. 对于支持虚拟内存的操作系统,你必须弄清楚"虚拟内存"在哪里。指针被允许访问的内存。阅读内存映射文件。
  4. 在某些平台上,地址0x0000是有效地址。验证在您的目标平台上是否存在这种情况。

恕我直言,指针内容可以验证,但验证可能非常复杂。

更倾向于使用引用

最新更新