【问题标题】:"Debug Assertion" Runtime Error on VS2008?VS2008 上的“调试断言”运行时错误?
【发布时间】:2011-02-16 16:08:23
【问题描述】:

我正在 VS2008 上编写一个 C++ MFC 程序,当我第一次运行该程序时有时会遇到这个“调试断言错误”。当我尝试调试它时,它会将我带到这个 winhand.cpp 文件,它不是我编写的程序的一部分,所以我不确定如何调试它。

将错误带到winhand.cpp中的这个地方

 CObject* pTemp = LookupTemporary(h);
 if (pTemp != NULL)
 {
  // temporary objects must have correct handle values
  HANDLE* ph = (HANDLE*)((BYTE*)pTemp + m_nOffset);  // after CObject
  ASSERT(ph[0] == h || ph[0] == NULL);
  if (m_nHandles == 2)
   ASSERT(ph[1] == h);
 }

那么为什么会发生这个错误呢?为什么它只是偶尔发生(50% 的时间)?我该如何调试呢?

如果需要,我会提供一些代码。

谢谢!

【问题讨论】:

  • HAN​​DLE* ph = (HANDLE*)((BYTE*)pTemp + m_nOffset);从对象中提取句柄似乎是一种不寻常的方式。你为什么这样做? LookUpTemporary() 返回什么?
  • 嗨安德斯,我不知道。这些代码不是我写的,它不是我程序的一部分。但这就是 VS2008 调试带我去的地方。
  • OIC,你可能需要开始注释掉你的原始代码,看看你的代码是什么导致了这个。
  • 那里有两个 ASSERT。哪一个在断言?如果是第一个,ph[0] 的值是多少?如果是第二个,h 和 ph[1] 的值是多少?报告十进制和十六进制值。

标签: c++ visual-studio-2008 mfc debugging


【解决方案1】:

断言的代码是 MFC 的 CHandleMap 类的一部分。 MFC 将窗口作为CWnd 对象处理,但Windows 将它们作为HWND 句柄处理。句柄映射允许 MFC 将HWND“转换”为指向表示该对象的 MFC 对象的指针。

断言似乎在做的是检查当句柄查找找到 MFC 对象时,MFC 对象是否也认为它正在包装相同的句柄。

如果它们不同,那么你就会得到断言。

所以看起来有些东西正在破坏句柄映射或该句柄的 MFC 对象,或者您正在做一些不正确的事情,导致这 2 个数据结构不同步。

尝试调试问题时您可能会做的一些事情是确定:

  • 在查找中找到了什么 MFC 对象(pObject 指向的对象)
  • MFC 对象认为它正在包装的内容(即句柄 ph[0] 和/或 ph[1] - 我不确定为什么会有 2 个)
  • 句柄是干什么用的(h

句柄看起来像句柄值还是看起来像垃圾? pObject 是否指向看起来像 MFC 对象或垃圾的东西?这些事情中的任何一个似乎相关吗?

这些问题的答案可能指向您下一步需要做什么(可能在看起来像是被丢弃的项目上设置一个调试写入断点)。

【讨论】:

    【解决方案2】:

    几天前我得到了同样的断言,经过一些谷歌搜索, 我在这里找到了适合我的案例的解决方案: http://forums.codeguru.com/showthread.php?216770-What-would-cause-this-assertion

    在我的情况下,改为误用

    CDC* dc = GetDC();
    CSize spaceSize = dc->GetTextExtent(" ");
    dc->DeleteDC();
    

    CDC* dc = GetDC();
    CSize spaceSize = dc->GetTextExtent(" ");
    ReleaseDC(dc);
    

    会解决的。

    【讨论】:

      【解决方案3】:

      注意这些方面的代码(来自 Stroustrup 书中的记忆):

      c1 = (t2+t3).c_str();
      

      (在精神上,当然可以是其他命令和表达式)。临时对象在其封闭的完整表达式被评估后被销毁,或者至少标准允许它们被销毁。这意味着您想分配给 c1 的内容可能仍然在内存中,也可能不在内存中,可以将其分配给 c1。编译器可能会提醒您注意此问题,问题可能会或可能不会出现,具体取决于您分配的具体内容和其他情况(我不是编译器编写者),这也可以解释为什么您有时会收到此错误消息。

      所以在你的情况下,我会扫描我的代码以查找类似的表达式并清理它们。

      【讨论】:

        【解决方案4】:

        当调试器中断时,将调用堆栈向上移动到你的代码的第一位(如果有的话——希望有!)。理想情况下,它就像代码中错误地调用库函数一样简单,并且库会通过断言捕获错误并提醒您注意这一点。 (我认为没有人能够从 library 代码中判断出什么问题,我们需要查看 您的 代码。)

        否则,您将面临一些棘手的调试问题:您对正在断言的库(看起来像 MFC)做错了,因此请返回并查看您的所有 MFC 代码,并确保一切正确并根据文档。

        【讨论】:

          【解决方案5】:

          这看起来有点像我今天早上遇到的错误。这是否发生在 OnIdle() 中?

          【讨论】:

            【解决方案6】:

            我知道这是一篇很老的帖子,但希望有人能从我的回答中得到一点帮助。

            由于我的简单错误,我最近也遇到了类似的问题,然后我偶然发现了这篇文章并从“pac”的帖子中得到了提示。

            我发现如果我使用 DeleteDC() 释放从 GetWindowDC() 或 GetDC() 返回的 DC,一旦 CPaintDC 对象实例超出范围,我将在 MFC 框架中获得上述断言。

            CDC * pDC = GetWindowDC();
            ...
            ReleaseDC(pDC);
            

            您必须仅将 DeleteDC() 与 CreateDC() API 结合使用。

            CDC * pDC = new CDC();
            pDC->CreateDC();
            ....
            pDC->DeleteDC();
            

            【讨论】:

              【解决方案7】:

              当我们的一些项目 dll 将 MFC 作为静态库和一些作为共享库链接时,我们遇到了这个问题(检查项目设置中的“使用 MFC”)

              【讨论】:

                猜你喜欢
                • 2015-06-27
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2022-12-14
                • 1970-01-01
                相关资源
                最近更新 更多