删除线程时崩溃

Posted

技术标签:

【中文标题】删除线程时崩溃【英文标题】: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 时)。

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

【问题讨论】:

【参考方案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 包装在课堂上,一切正常。问题解决了

以上是关于删除线程时崩溃的主要内容,如果未能解决你的问题,请参考以下文章

iOS进阶 - iOS如何监控崩溃

iOS进阶 - iOS如何监控崩溃

尝试加入时线程崩溃

使用 python 线程时,python 因核心转储而崩溃

线程退出时应用程序崩溃 - C++

核心数据和多线程在保存时崩溃