首页 > 解决方案 > MFC 调试断言失败!!wincore.cpp 第 972 行

问题描述

我在 DLL 中创建了一个 MFC 对话框,用于多个项目,它具有以下功能:使用 DLL 从主应用程序获取列表框数据。我可以通过主应用程序将字符串数据推送到 MFC 对话框,但编译后出现断言错误。此过程发生在一个线程中,其中一个线程保持对话框处于活动状态,另一个线程推送数据,如下面的代码所示。

void dbox(CDialogClass *dlg)
{
    dlg->ShowDlg();
    
}

void input(CDialogClass *dlg)
{
    string str1= "";
    while (1)
    {
        getline(cin, str1);
        //cin >> str1;
        dlg->SetData(str1);
        
    }
}

int main()
{
    HMODULE hModule = ::GetModuleHandle(NULL);
    if (hModule != NULL)
    {
        // initialize MFC and print and error on failure
        if (!AfxWinInit(hModule, NULL, ::GetCommandLine(), 0))
        {
            _tprintf(_T("Fatal Error: MFC initialization failed\n"));
        }
        else
        {
            CDialogClass *dlg = new CDialogClass("Title Dbox",300.0f, 300.0f, 0);
            thread t1(input, dlg);
            thread t2(dbox, dlg);
            t1.join();
            t2.join();
        }
    }
    return 0;
}

此处 dbox() 调用位于 MFC DLL 中的 ShowDlg 函数,如下所示:

void CDialogClass::ShowDlg()
{
    dlgg->title = title;
    dlgg->dialogWidth = D_width;
    dlgg->dialogHeight = D_height;
    dlgg->pos = pos;

    dlgg->Create(IDD_DIALOG1);
    
    dlgg->ShowWindow(SW_SHOWNORMAL);
    dlgg->RunModalLoop();
    //dlgg->DoModal();  
}

SetData() 由线程 input() 调用,它在 DLL 中有以下代码:

void CDialogClass::SetData(string data)
{
    p_text = data;
    dlgg->calldata(data);
}

下面是 DLL 中我的 Dialog 类的代码,仅供参考(如果需要)-


#include "stdafx.h"
#include "DlgDisp.h"
#include "afxdialogex.h"
#include "Resource.h"
#include <fstream>
#include <Thread>

IMPLEMENT_DYNAMIC(CDlgDisp, CDialogEx)

CDlgDisp::CDlgDisp(CWnd* pParent /*=NULL*/)
    : CDialogEx(CDlgDisp::IDD, pParent)
{
}

CDlgDisp::~CDlgDisp()
{
}

void CDlgDisp::DoDataExchange(CDataExchange* pDX)
{
    CDialogEx::DoDataExchange(pDX);

    DDX_Control(pDX, IDC_LIST1, m_listbox);
}

BOOL CDlgDisp::OnInitDialog()
{
    //Title manipulations
    char *str_title;
    str_title = &title[0];
    SetWindowText((CAtlString)str_title);

    //Size manipulations
    CWnd* pctrl = GetDlgItem(IDC_LIST1);
    CRect rectctrl;
    SetWindowPos(NULL, 0, 0, dialogWidth, dialogHeight, SWP_NOMOVE | SWP_NOZORDER);
    pctrl->GetWindowRect(rectctrl);
    pctrl->SetWindowPos(NULL, 20, 20, dialogWidth-120, dialogHeight-80, SWP_NOMOVE | SWP_NOZORDER);

    UpdateData(FALSE);
    return TRUE;  // return TRUE  unless you set the focus to a control
}

BEGIN_MESSAGE_MAP(CDlgDisp, CDialogEx)

END_MESSAGE_MAP()

void CDlgDisp::calldata(string strdata)
{
    char *str_parameter;
    str_parameter = &strdata[0];
    CString param = _T("");
    param.Format(_T("%s"), (CAtlString)str_parameter);
    if (pos == 0)
    {
        m_listbox.InsertString(0, param);
    }
    else
        m_listbox.AddString(param);
    UpdateData(FALSE);
}

程序流程供参考:

CDlgDisp 类是从 CDialogEx 类派生的 Dialog 类。CDialogClass 用于与派生自 CDialog 类的外部应用程序进行交互。CDialogClass 有一个 CDlgDisp 类的公共成员变量。

外部应用程序 -> object.CdialogClass -> object.CDlgdisp 类

当我执行程序时它运行良好,当我尝试通过控制台输入数据时出现错误。它确实会动态地打印在列表框中,但随后会显示断言错误。

这是执行后的图像[在此处输入图像描述][1]

这是我在控制台中输入数据并按回车后的图像 [在此处输入图像描述] [2]

你们认为问题是什么?[1]:https ://i.stack.imgur.com/pXFMD.png [2]:https ://i.stack.imgur.com/eUXZ7.png

标签: c++multithreadingdllmfc

解决方案


查看发生 ASSERT 离子的源

你会发现这条评论:

    // Note: if either of the above asserts fire and you are
    // writing a multithreaded application, it is likely that
    // you have passed a C++ object from one thread to another
    // and have used that object in a way that was not intended.
    // (only simple inline wrapper functions should be used)
    //
    // In general, CWnd objects should be passed by HWND from
    // one thread to another.  The receiving thread can wrap
    // the HWND with a CWnd object by using CWnd::FromHandle.
    //
    // It is dangerous to pass C++ objects from one thread to
    // another, unless the objects are designed to be used in
    // such a manner.

MFC 窗口对象使用每个线程的句柄映射。这通常不允许您将对象用于其他线程的某些功能。这是可能的,但这在许多其他线程中都有讨论。

您想使用 MFC 的方式是不可能的。考虑同步。如果函数是线程安全的并且您想与其他窗口一起使用,您可以直接使用 SendMessage 和 m_hWnd 句柄。


推荐阅读