zoukankan      html  css  js  c++  java
  • 慎用传指针方式向线程传递局部变量

    今天编译了一段程序,运行的时候崩溃了,下断点查看了下崩溃的地方,发现问题出在使用传指针方式向线程传递局部变量。问题代码大致如下:

    void CStrLenCheckDlg::OnOK()
    {
    THREADINFO info; // 局部变量
    info.pDlg = this;
    info.strFileName = m_strFileName;

    // 以传指针方式传递局部变量 info 给线程函数
    AfxBeginThread(ThreadFunc, &info);
    }


    UINT ThreadFunc(LPVOID lpParam)
    {
    THREADINFO* pInfo = (THREADINFO*)lpParam;

    if (NULL != pInfo && NULL != pInfo->pDlg)
    {
    pInfo->pDlg->CheckPath(pInfo->strFileName);

    // 崩溃语句,pInfo->pDlg 的内存地址与原来不同
    pInfo->pDlg->GetDlgItem(IDOK)->EnableWindow(FALSE);
    }

        return 0;
    }

    当 AfxBeginThread() 执行结束后,主线程从 CStrLenCheckDlg::OnOK() 函数返回。但是,新创建的线程的线程函数 ThreadFunc() 仍就在执行中,此时问题就出来了。向线程函数 ThreadFunc() 传递的参数 info 是在 CStrLenCheckDlg::OnOK() 中定义的局部变量,当 CStrLenCheckDlg::OnOK() 返回时,局部变量 info 的内存中已经被释放。此时,ThreadFunc() 读取了一段被释放的内存,势必出现问题。

    解决方法有二:一个是 new 出一个 info 变量,然后由线程函数 ThreadFunc() 负责 delete 掉;另一个是将 info 变量传入后立即在线程函数 ThreadFunc() 中拷贝一份副本。

    方法一:

    void CStrLenCheckDlg::OnOK()
    {
    THREADINFO* pInfo = new THREADINFO;
    pInfo->pDlg = this;
    pInfo->strFileName = m_strFileName;
    AfxBeginThread(ThreadFunc, pInfo);
    }


    UINT ThreadFunc(LPVOID lpParam)
    {
    THREADINFO* pInfo = (THREADINFO*)lpParam;

    if (NULL != pInfo && NULL != pInfo->pDlg)
    {
    pInfo->pDlg->CheckPath(pInfo->strFileName);
    pInfo->pDlg->GetDlgItem(IDOK)->EnableWindow(FALSE);
    }

    delete pInfo;

        return 0;
    }

    方法二:

    void CStrLenCheckDlg::OnOK()
    {
    THREADINFO info; // 局部变量
    info.pDlg = this;
    info.strFileName = m_strFileName;

    // 以传指针方式传递局部变量
    AfxBeginThread(ThreadFunc, &info);
    }


    UINT ThreadFunc(LPVOID lpParam)
    {
    if (NULL != lpParam)
    {
    THREADINFO info = *((THREADINFO*)lpParam);

    if (NULL != info.pDlg)
    {
    info.pDlg->CheckPath(info.strFileName);
    info.pDlg->GetDlgItem(IDOK)->EnableWindow(FALSE);
    }
    }

    return 0;
    }

    方法二中代码不能保证在拷贝副本的时候 CStrLenCheckDlg::OnOK() 函数未返回,为了万无一失可以使用信号量来做延迟。

  • 相关阅读:
    我理解的SNS(一)
    获取某命名规则下一系列表的总条数
    lock后日志干净了
    设计模式学习系列之UML图(创建型模式)
    CLR实用特征异常
    arcgis api for flex 高级主题(一) esri tilemap 四叉树索引研究<转>
    arcgis api for flex 开发入门(三)地图浏览控件的使用<转>
    深入浅出 Javascript API(三)地图配置<转>
    深入浅出 Javascript API(四)绘制 Graphics<转>
    arcgis api for flex 开发入门(二)map 的创建<转>
  • 原文地址:https://www.cnblogs.com/wxxweb/p/2336784.html
Copyright © 2011-2022 走看看