useready
2017-03-30 23:31
采纳率: 100%
浏览 3.2k

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;
            }
        }
    
    
    }
    
    点赞 打赏 评论
  • GKatHere 2017-04-01 03:53

    delete[] pParam;
    错了,应当
    delete dlg ;
    因为上面上不会调用析构函数

    点赞 打赏 评论
  • GKatHere 2017-04-01 15:33
    for (int i = 0; i < nLineCount; i++)
    //...
     int nNull = 0, nBegin = i - nThreadAll, nEnd = i;   // nBegin <0; 什么意思、 nBegin=0吧
     for (int j = nBegin; j < nEnd; j++)
            {
                if (m_Table[j][1].IsEmpty())  //  不然 m_Table[j];j小于0
                {
                    nNull++;
                    Sleep(100);
                }
            }
    
    
    点赞 打赏 评论
  • GKatHere 2017-04-02 01:22

    把全局变量封装一下,原程序lock, unlock对全局变量并未完全用到
    ps: 手写,未检测

    
    //vector<vector<CString>> m_Table;
    
    struct SCPCCriticalSection
    {
        CCriticalSection& cs;
        SCPCCriticalSection(CCriticalSection& cs_) :cs(cs_)
        {
            cs.Lock();
        }
        ~SCPCCriticalSection()
        {
            cs.Unlock();
        }
    };
    struct LineTable
    {
        vector<vector<CString>> m_Table;
        CCriticalSection cs;
    
        void resize(int f, int s)
        {
            SCPCCriticalSection scp(cs);
    
            m_Table.resize(f);
            for (int n=0; n<f; n++)
                m_Table[n].resize(s);
        }
    
        BOOL set(int f, int s, const char* str)
        {
            SCPCCriticalSection scp(cs);
    
            if (f >= m_Table.size() || s >= m_Table[f].size())
                return false;
            m_Table[f][s] = str;
            return true;
        }
    
        BOOL IsEmpty(int f, int s)
        {
            SCPCCriticalSection scp(cs);
    
            if (f >= m_Table.size() || s >= m_Table[f].size())
                return true;
            return m_Table[f][s].IsEmpty();
        }
    };
    
    //...
       CString strFlag = TestTest(dlg->nIdx, dlg->strName);
        if (strFlag == "成功")
        {
            //cs.Lock();
            //m_Table[dlg->nIdx][2] = 业务代码...
            g_LineTable.set(dlg->nIdx, 2, 业务代码...);
        }
        //m_Table[dlg->nIdx][1] = strFlag;
       // cs.Unlock();
        g_LineTable.set(dlg->nIdx, 2, strFlag);
    
        //.....
        //if (m_Table[j][1].IsEmpty())
                    if (g_LineTable.IsEmpty(j, 1))
            //.....
            //if (m_Table[i][1].IsEmpty())
                if (g_LineTable.IsEmpty(i, 1))
    
    点赞 打赏 评论
  • useready 2017-04-08 06:27

    你好,用这种方式测试了下偶尔还是会报内存不能为“read”的错误(0xf7d7d9b2). 实在头疼,不知道是不是网上说的CString不能用作结构体?

    点赞 打赏 评论

相关推荐 更多相似问题