Visual Studio C++ MFC 堆栈跟踪,大部分只是外部堆栈帧 - 查找原因

问题描述 投票:0回答:1

我在 Visual Studio 中使用 C++ MFC 的应用程序有一个堆栈跟踪,该应用程序已崩溃。

我打开了调试器,并带有堆栈跟踪,但我无法判断原因是什么。除了调用显示模式对话框的入口点之外,所有堆栈帧都是外部的。


我怎样才能找到这个问题的原因,或者调试这个问题? (为什么堆栈不是我代码的,而是全部外部的?)


这是堆栈frame中唯一与我的代码相关的调用。

   INT_PTR nResponse = dlg->DoModal();


错误断点在这里:

ASSERT(ph[1] == h);

   #ifdef _DEBUG
   void CHandleMap::RemoveHandle(HANDLE h)
   {
    // make sure the handle entry is consistent before deleting
    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); <------
    }
    pTemp = LookupPermanent(h);
    if (pTemp != NULL)
    {
        HANDLE* ph = (HANDLE*)((BYTE*)pTemp + m_nOffset);  // after CObject
        ASSERT(ph[0] == h);
        // permanent object may have secondary handles that are different
    }
    // remove only from permanent map -- temporary objects are removed
    //  at idle in CHandleMap::DeleteTemp, always!
    m_permanentMap.RemoveKey((LPVOID)h);
   }
   #endif

从堆栈跟踪中我可以看到 CDC 正在开始分离,在此之前会调用

CStatusBar
OnNCPaint
。我还使用调试器检查了 WindowProc 消息值,它是 133。我查了一下 133 是什么,它与
0085     133     WM_NCPAINT
相关。除了 CDC 可能被释放之外,一切似乎都无关紧要。

我怀疑当应用程序最小化时会发生这种情况 - 一个疯狂的猜测,因为我认为这就是我在它崩溃时所做的 - 也很难重现。

这是我的状态栏代码,可能适用,请注意它是从 OnTimer 调用的。

void MainDlg::OnTimer(UINT_PTR nIDEvent)
{
   if (nIDEvent == nTimerStatusbarUpdate)
   {
       if (statusBarHelper == nullptr) return;

      // snip...

      statusBarHelper->UpdateRightPanelWidthAndText(text);
   }
}


// the helper class method
void StatusBarHelper::UpdateRightPanelWidthAndText(const CString& text)
{
   if (statusbar_mutex.try_lock_for(std::chrono::seconds(1))) {
      CDC* pDC = statusBar.GetDC();
      If (pDC == nullptr)
      {
        // Failed to get device context
        statusbar_mutex.unlock();
        return;
      }
 
      // snip....

      // Release the device context and restore the original font
      pDC->SelectObject(pOldFont);
      statusBar.ReleaseDC(pDC);
      statusbar_mutex.unlock();
   }
}

visual-studio winapi visual-c++ mfc
1个回答
0
投票

正如 @IInspectable 指出的,它不是堆栈跟踪而是断言,它是 GDI 垃圾收集的一部分。

这是由调用分离 CDC 引起的,而一开始就不应该调用它。

CDC* pDC = CDC::FromHandle(lpDrawItemStruct->hDC);

// snip 

pDC->Detach(); <-- the error

CDC::FromHandle
返回指向 CDC 的指针,该指针不受您的控制。

在我的例子中,被引用的 CDC 是在 DrawItem 方法中。

Clazz::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct) { ... }

来自 Microsoft 文档

CDC::DeleteTempMap 由 CWinApp 空闲时间处理程序调用,以删除由 FromHandle 创建的任何临时 CDC 对象。还分离设备上下文。

© www.soinside.com 2019 - 2024. All rights reserved.