【问题标题】:Breakpoints out of nowhere when debugging with gdb, inside ntdll在 ntdll 中使用 gdb 进行调试时突然出现断点
【发布时间】:2009-10-25 14:32:43
【问题描述】:

我做了一个非常简单的程序,它为我自动完成了一些事情。我用 C++ 编写了它,它在 Windows 上运行。在 Codeblocks IDE 内部使用 GDB 对其进行调试时,我突然得到了许多断点。我不知道是什么导致了这个问题。断点似乎与内存问题有关......因为当我修复检测到的内存泄漏时,断点数量明显减少。

gdb 告诉我的确切内容是:

 Program received signal SIGTRAP, Trace/breakpoint trap.
 In ntdll!TpWaitForAlpcCompletion () (C:\Windows\system32\ntdll.dll)

我在我的程序中多次遇到这种情况。我认为我可能做错了什么,即使该程序似乎运行得很好并且它完成了我想要它做的事情。谁能告诉我是什么问题,因为我不知道在哪里看?另外,如果这不是问题,那么有谁知道如何禁用它,因为这会阻止我到达我自己设置的断点?

提前致谢!

编辑:(添加 GDB 的 where 命令的输出): 我在哪里可以检查每个函数的作用,以便我可以看到我做错了什么?

#0  0x76fefadd in ntdll!TpWaitForAlpcCompletion () from C:\Windows\system32\ntdll.dll
#1  0x0028e894 in ?? ()
#2  0x76fb272c in ntdll!RtlCreateUserStack () from C:\Windows\system32\ntdll.dll
#3  0x00657fb8 in ?? ()
#4  0x00657fb8 in ?? ()
#5  0x76f4b76a in ntdll!RtlDowncaseUnicodeChar () from C:\Windows\system32\ntdll.dll
#6  0x02070005 in ?? ()
#7  0x00000b10 in ?? ()
#8  0x0028e8dc in ?? ()
#9  0x76ff0b37 in ntdll!TpQueryPoolStackInformation () from C:\Windows\system32\ntdll.dll
#10 0x038b0000 in ?? ()
#11 0x00657fb8 in ?? ()
#12 0x76f4b76a in ntdll!RtlDowncaseUnicodeChar () from C:\Windows\system32\ntdll.dll
#13 0x6e6e9a5e in ?? ()
#14 0x038b0000 in ?? ()
#15 0x038b0000 in ?? ()
#16 0x00000000 in ?? ()

【问题讨论】:

  • 当您获得 SIGTRAP 时,调用堆栈的其余部分是什么样的?请发布 GDB“where”命令的输出。
  • 感谢您的回复,我将在问题中附加“where”的输出。正在编辑...

标签: debugging gdb


【解决方案1】:

虽然这个问题现在已经很老了,但这里有一些要点可能会对像我一样在搜索后来到这里的人有所帮助:

我刚刚在 Win7 上测试我在 WinXP 上开发的应用程序时遇到了这个问题。在我的情况下,它与 Windows 7 内存管理监控和我的应用程序中的错误内存分配有关。

简而言之,在应用程序代码中,一个内存块被错误分配(而不是使用 GlobalAlloc())并被 GlobalFree() 释放(这是错误的,因为系统堆是使用来自 C 运行时内存池的指针)。虽然这会导致(在这种情况下非常小)内存泄漏,但在 WinXP 上进行测试时完全没有注意到,整个程序显然运行正确。

现在在 Win7 上执行时,名为 Fault Tolerant Heap (FTH) 的内存监控功能会检测到应用程序的此错误(导致异常):

  • 同时它通过OutputDebugString()(或者DbgPrint())输出一些信息,这些信息可以使用简单的DebugView 工具查看,或者在跟踪应用程序时由任何调试器查看。因此,在收到信号之前,您可以在消息中看到类似的内容:

    警告:HEAP[name_of_your.exe]:

    警告:指定给 RtlFreeHeap(006B0000, 006A3698) 的地址无效

  • 并且(在调试应用程序的情况下)它会输出一个断点,该断点在调试器之外没有任何影响,但其他应该有助于指出问题。 GDB 将断点显示为 SIGTRAP 信号

此时您有 2 个选择:

  • 尝试遍历调用堆栈以查找代码中的错误指令(不幸的是,在这种情况下,btwhere gdb 命令无法显示足够远以查看我的代码中堆被错误释放的位置 - 如果有人知道如何从起始模块而不是 ntdll 显示正确的调用堆栈,请告诉我)
  • 尝试继续,因为 FTH 能够在内存中自动修补以尝试解决您的错误(该自动修补也可以在下次运行应用程序时提前发生)

如 Moshe Levi 所说,为了在堆问题时不停止,您可以在启动应用程序之前在 GDB 提示符处设置 handle SIGTRAP nostop

简而言之:是的,您的代码确实存在与内存管理相关的问题,但在某些情况下,它可以运行而不会崩溃。但在调试模式下,内核会尝试将您置于问题的路径上。

【讨论】:

  • 我要补充一点,看起来代码并不总是错误的。我有一个非常相似的问题,并看到警告Heap block at 003E5E78 modified at 003E5EBA past requested size of 3a。我什至发现了触发警告的错误位置,并且代码看起来很好:我用«new»创建了«wchar_t»数组,然后用«delete[]»释放它。可能是 MinGW 中的一个错误。顺便说一句,有一件事间接证实了这一点:我在 GNU/Linux 上使用 valgrind 测试了该应用程序,但没有发现任何问题。
【解决方案2】:

哇,你让我回到了 5 年前我在 linux 平台上使用 gdb 的时候:)

您可以使用以下命令防止 gdb 在接收 SIGTRAP 时中断:

handle SIGTRAP nostop

但我和 steve 在一起,请改用 WinDbg。它是专门为 Windows 构建的。

【讨论】:

  • 您认为在哪里可以获得免费的 WinDbg? AFAIK 它仅与 Visual Studio 一起提供,我怀疑有人会因为调试器而购买它,这甚至不是更好的 gdb。但是 ⁺¹ 无论如何:我什至没有注意到系统库中的断点会导致另一个信号,与通常的中断不同。
  • WinDbg 是免费的,并且作为 Windows 调试工具包的一部分提供。你可以从microsoft.com/click/services/Redirect2.ashx?CR_EAC=300135395下载它
【解决方案3】:

我建议使用本机 Windows 调试器 WinDBG。这将提供更好的堆栈跟踪,尤其是在符号转换到内核模式时。

【讨论】:

    【解决方案4】:

    我刚刚在 Qt Creator 中使用 gcc/mingw 时遇到了这个崩溃。

    我也遇到了其他问题,包括似乎错误的变量(偏移 6 个字节)。 就我而言,它原来是一个对代码造成严重破坏的编译指示包。

    我有这个:

    #pragma pack(1)
    typedef struct SomeStruct
    {
    ... // structure
    } SomeStruct;
    

    ...但是我没有在结构之后调用 pragma pack() 来终止它,以结束 1 的打包并返回到默认的字节对齐/打包。添加修复它:

    #pragma pack(1)
    typedef struct SomeStruct
    {
    ... // structure
    } SomeStruct;
    #pragma pack() // <<-- with this line the heap corruption problem was stopped
    

    【讨论】:

      猜你喜欢
      • 2019-05-13
      • 2021-09-12
      • 1970-01-01
      • 1970-01-01
      • 2014-08-29
      • 1970-01-01
      • 2022-10-16
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多