在主线程用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;
}
你检测下其它程序吧,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;
}
}
}
delete[] pParam;
错了,应当
delete dlg ;
因为上面上不会调用析构函数
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);
}
}
把全局变量封装一下,原程序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))
你好,用这种方式测试了下偶尔还是会报内存不能为“read”的错误(0xf7d7d9b2). 实在头疼,不知道是不是网上说的CString不能用作结构体?