【问题标题】:Crash when thread is deleted删除线程时崩溃
【发布时间】:2014-01-20 13:59:15
【问题描述】:

我正在使用 MFC 开发应用程序。 UI 线程启动一个工作线程并在应用程序关闭时停止它。问题是应用程序每次尝试删除线程时都会崩溃。

这里是代码:

首先是线程类及其实现:

class FileThread : public CWinThread
{
public:
    static FileThread* CreateWorkerThread(LPVOID params, UINT priority, UINT flags);

    void InitThread();
    void StopThread();
    inline HANDLE GetStopHandle() const { return m_stopThread; }
    inline HANDLE GetWaitHandle() const { return m_waitThread; }

private:
    HANDLE m_stopThread;
    HANDLE m_waitThread;

    FileThread(): m_stopThread(NULL), m_waitThread(NULL) { }

    static UINT MyThreadProc(LPVOID pParam);
};

FileThread* FileThread::CreateWorkerThread(LPVOID params, UINT priority, UINT flags)
{
    return (FileThread*) AfxBeginThread(FileThread::MyThreadProc, params, priority, 0,  flags);
}

void FileThread::InitThread()
{
    m_stopThread = CreateEvent(0, TRUE, FALSE, 0);
    m_waitThread = CreateEvent(0, TRUE, FALSE, 0);
}

void FileThread::StopThread()
{
    ::SetEvent(m_stopThread);
    ::WaitForSingleObject(m_waitThread, INFINITE);
    ::CloseHandle(m_stopThread);
    ::CloseHandle(m_waitThread);
}


UINT FileThread::MyThreadProc(LPVOID pParam)
{
    ThreadData* pLink = (ThreadData*)pParam;
    BOOL continueProcess = TRUE;
    int returnCode = EXITCODE_SUCCESS;

    while (continueProcess)
    {
        if(::WaitForSingleObject(pLink->pMe->GetStopHandle(), 0) == WAIT_OBJECT_0)
        {
            ::SetEvent(pLink->pMe->GetWaitHandle());
            continueProcess = FALSE;
        }

        // the thread is looking for some files...
    }

    delete pLink; // it was allocated from the UI thread

    return returnCode;
}

然后,我开始线程:

ThreadData * td = new ThreadData();

m_myFileThread = FileThread::CreateWorkerThread((LPVOID)td, THREAD_PRIORITY_LOWEST, CREATE_SUSPENDED);

td->pMe = m_myFileThread;
m_myFileThread->m_bAutoDelete = FALSE;

m_myFileThread->InitThread();
m_myFileThread->ResumeThread();

最后,停止(和崩溃):

DWORD exitCode;
if (m_myFileThread != NULL && GetExitCodeThread(m_myFileThread->m_hThread, &exitCode) && (exitCode == STILL_ACTIVE))
    {
        m_myFileThread->StopThread();
        if(::WaitForSingleObject(m_myFileThread->m_hThread, 5000) == WAIT_TIMEOUT)
        {
            TerminateThread(m_myFileThread->m_hThread, EXITCODE_ABORT);
        }
    }

if (m_myFileThread != NULL)
{ 
    delete m_myFileThread; // => CRASH
}

似乎我尝试删除已删除的内容并最终导致堆损坏。我尝试将 m_bAutoDelete 设置为 TRUE,并且我自己没有删除线程,但我遇到了同样的崩溃(当程序试图调用 AfxEndThread 时)。

线程终止其线程过程并返回退出代码。

【问题讨论】:

    标签: c++ multithreading mfc heap-corruption


    【解决方案1】:

    在我看来这里有问题:

    FileThread* FileThread::CreateWorkerThread(LPVOID params, UINT priority, 
                                               UINT flags)
    {
        return (FileThread*) AfxBeginThread(FileThread::MyThreadProc, params, 
                                            priority, 0,  flags);
    }
    

    AfxBeginThread 返回一个CWinthread*,因此仅将其转换为您自己的派生类不会使其成为该派生类的实例。我很惊讶它完全有效。

    与其从CWinThread 派生FileThread,不如在包装类中保存CWinthread* 成员变量并在必要时通过访问器公开线程句柄。

    【讨论】:

    • 下面的 MSDN 示例展示了如何正确地进行转换msdn.microsoft.com/en-us/library/z2h4xz23.aspx CWinthread 也有一个自动删除机制:msdn.microsoft.com/en-us/library/4bbe9bte.aspx
    • @odedsh 嗯,有点像,它创建了一个 UI 线程,它有一个消息泵(需要用于套接字) - 它 可以 用作工作线程,但它可能是一个在许多情况下有点矫枉过正。
    • @Roger Rowland:这就是你认为的那种问题“当然,伙计!我有那么愚蠢吗?!” ;) 非常感谢,我将 CWinThread 包装在课堂上,一切正常。问题解决了
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-07-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多