useready 2017-03-30 23:31 采纳率: 100%
浏览 3323
已采纳

C++多线程内存泄漏问题

在主线程用AfxBeginThread开启子线程时,偶尔会报内存泄漏的错误(单线程没问题)
不是频繁报,10次有1~2次的样子,debug我也不知道怎么跟踪,怀疑是锁的问题加上
CCriticalSection cs; cs.Lock();cs.Unlock();后发现还是不行,求助!

 /*结构体*/
typedef struct _dlgTag
{
    int nIdx;
    CString strName;
} DLGTAG;



/*主线程代码*/
//初始化数组
m_Table.clear();
m_Table.swap(vector<vector<CString>>());
m_Table.resize(nLineCount);
for (int i = 0; i < nLineCount; i++)
{
    m_Table[i].resize(3);
}

//遍历
nThreadNum = 0;
nThreadAll = 30;
for (int i = 0; i < nLineCount; i++)
{
    //多线程工作
    if (nThreadNum < nThreadAll)
    {
        DLGTAG *dd = new DLGTAG();
        dd->nIdx = i;
        dd->strName = strLine;
        AfxBeginThread(LoopWorkThread, (LPVOID)dd);
        nThreadNum++;
        continue;
    }

    //轮巡线程池
    while (1)
    {
        int nNull = 0, nBegin = i - nThreadAll, nEnd = i;
        switch (nBegin)
        {
        case 0:
            nBegin++;
            nEnd++;
            break;
        default:
            break;
        }
        for (int j = nBegin; j < nEnd; j++)
        {
            if (m_Table[j][1].IsEmpty())
            {
                nNull++;
                Sleep(100);
            }
        }

        //已完成数
        if (nThreadAll - nNull > 0)
        {
            nThreadNum = nNull;
            i--;
            break;
        }
    }
}

//遍历结束检查线程是否全部执行完毕
while (1)
{
    int nNull = 0, nDone = 0;
    for (int i = 0; i < nLineCount; i++)
    {
        if (m_Table[i][1].IsEmpty())
        {
            nNull++;
            Sleep(100);
        }
    }
    nDone = nLineCount - nNull;
    if (nDone >= nLineCount)
    {
        break;
    }
}


/*子线程LoopWorkThread代码*/
CCriticalSection cs;
UINT LoopWorkThread(LPVOID pParam)
{
    DLGTAG* dlg = (DLGTAG*)pParam;
    CString strFlag = TestTest(dlg->nIdx, dlg->strName);
    if (strFlag == "成功")
    {
        cs.Lock();
        m_Table[dlg->nIdx][2] = 业务代码...
    }
    m_Table[dlg->nIdx][1] = strFlag;
    cs.Unlock();
    delete dlg;
    return 0;
}
  • 写回答

5条回答

  • GKatHere 2017-04-09 03:25
    关注

    你检测下其它程序吧,VS2010 无error,无leak

     /*结构体*/
    #include <vector>
    using namespace std;
    typedef struct _dlgTag
    {
        int nIdx;
        CStringA strName;
        ~_dlgTag(){};
    } DLGTAG;
    
    struct SCPCCriticalSection
    {
        CCriticalSection& cs;
        SCPCCriticalSection(CCriticalSection& cs_) :cs(cs_)
        {
            cs.Lock();
        }
        ~SCPCCriticalSection()
        {
            cs.Unlock();
        }
    };
    struct LineTable
    {
    private:
        vector<vector<CString>> m_Table;
        CCriticalSection cs;
    
        bool CheckTalbeSize(size_t f, size_t s) //  
        {
            return f < m_Table.size() && s < m_Table[f].size();
        }
    public:
        void resize(size_t f, size_t s)
        {
            SCPCCriticalSection scp(cs);
    
            m_Table.resize(f);
            for (size_t n=0; n<f; n++)
                m_Table[n].resize(s);
        }
    
        BOOL set(size_t f, size_t s, const char* str)
        {
            SCPCCriticalSection scp(cs);
    
            ASSERT(CheckTalbeSize(f, s));
            if (f >= m_Table.size() || s >= m_Table[f].size())
                return false;
            m_Table[f][s] = str;
            return true;
        }
    
        BOOL IsEmpty(size_t f, size_t s)
        {
            SCPCCriticalSection scp(cs);
    
            ASSERT(CheckTalbeSize(f, s));
            if (f >= m_Table.size() || s >= m_Table[f].size())
                return true;
            return m_Table[f][s].IsEmpty();
        }
    };
    
    LineTable g_LineTable;
    
    //
    const char*  TestTest(int nIdx, const char* strName)
    {
        OutputDebugStringA(strName);
        if (nIdx&1)
            return "成功";
        else 
            return "失败";
    }
    
    /*子线程LoopWorkThread代码*/
    UINT LoopWorkThread(LPVOID pParam)
    {
        DLGTAG* dlg = (DLGTAG*)pParam;
        CStringA strFlag = TestTest(dlg->nIdx, dlg->strName);
        if (strFlag == "成功")
        {
            //cs.Lock();
            //m_Table[dlg->nIdx][2] = 业务代码...
            BOOL b =g_LineTable.set(dlg->nIdx, 2, "业务代码...");
            ASSERT(b);
        }
     //   m_Table[dlg->nIdx][1] = strFlag;
       // cs.Unlock();
        BOOL b =g_LineTable.set(dlg->nIdx, 1, strFlag);
        ASSERT(b);
    
        delete dlg;
        return 0;
    }
    
    
    void CListCtrlEx测试Dlg::OnBnClickedButton1()
    {
        // TODO: 在此添加控件通知处理程序代码
    
        /*主线程代码*/
        //初始化数组
    //  m_Table.clear();
    //  m_Table.swap(vector<vector<CString>>());
    //  m_Table.resize(nLineCount);
    //  for (int i = 0; i < nLineCount; i++)
    //  {
    //      m_Table[i].resize(3);
    //  }
    
        //遍历
        int nThreadNum = 0;
        int nThreadAll = 100;
        const int nLineCount =150;
        g_LineTable.resize(nLineCount, 3);
        const char* strLine = "strLine";
        for (int i = 0; i < nLineCount; i++)
        {
            //多线程工作
            if (nThreadNum < nThreadAll)
            {
                DLGTAG *dd = new DLGTAG();
                dd->nIdx = i;
                dd->strName = strLine;
                AfxBeginThread(LoopWorkThread, (LPVOID)dd);
                nThreadNum++;
                continue;
            }
    
            //轮巡线程池
            while (1)
            {
                int nNull = 0, nBegin = i - nThreadAll, nEnd = i;
                switch (nBegin)
                {
                case 0:
                    nBegin++;
                    nEnd++;
                    break;
                default:
                    break;
                }
                for (int j = nBegin; j < nEnd; j++)
                {
                    //if (m_Table[j][1].IsEmpty())
                    if (g_LineTable.IsEmpty(j, 1))
                    {
                        nNull++;
                        Sleep(100);
                    }
                }
    
                //已完成数
                if (nThreadAll - nNull > 0)
                {
                    nThreadNum = nNull;
                    i--;
                    break;
                }
            }
        }
    
        //遍历结束检查线程是否全部执行完毕
        while (1)
        {
            int nNull = 0, nDone = 0;
            for (int i = 0; i < nLineCount; i++)
            {
                //if (m_Table[i][1].IsEmpty())
                if (g_LineTable.IsEmpty(i, 1))
                {
                    nNull++;
                    Sleep(100);
                }
            }
            nDone = nLineCount - nNull;
            if (nDone >= nLineCount)
            {
                break;
            }
        }
    
    
    }
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(4条)

报告相同问题?

悬赏问题

  • ¥15 有赏,i卡绘世画不出
  • ¥15 如何用stata画出文献中常见的安慰剂检验图
  • ¥15 c语言链表结构体数据插入
  • ¥40 使用MATLAB解答线性代数问题
  • ¥15 COCOS的问题COCOS的问题
  • ¥15 FPGA-SRIO初始化失败
  • ¥15 MapReduce实现倒排索引失败
  • ¥15 ZABBIX6.0L连接数据库报错,如何解决?(操作系统-centos)
  • ¥15 找一位技术过硬的游戏pj程序员
  • ¥15 matlab生成电测深三层曲线模型代码