现在是这样的,我在CProcess类中定义了
typedef struct AccountEncFileList
{
CString arrayUserAccount;
CString arrayUserName;
list<CString> listEncFile;
}ACCOUNT_ENCFILE;
map<CString, ACCOUNT_ENCFILE> m_mapAccountEncFile;
在CProcess.cpp中使用
void CProcess::myProcess()
{
//初始化保存用户和对应加密文档的列表
m_mapAccountEncFile.clear();
for(int iR= 0; iR<4; iR++)
{
if ( g_bStopCheckFileType)
{
break;
}
....
pEncrypt.Encrypt(iR, m_ArrayFileName, ArrayEncFile, m_RightInfo, m_dlgProgress, g_bStopCheckFileType);
int isize = m_mapAccountEncFile.size();
SortAccountEncFile(userInfo, ArrayEncFile, m_mapAccountEncFile);
...
}
}
Encrypt是自定义的一个加密类中的函数,在Encrypt中
void CEncryptCtrl::Encrypt(int iRow, CStringArray & ArrayFile, CStringArray & ArrayEncFile, CRightInfo pRightInfo, CProgressDlg &dlgProgress, BOOL bStop)
{
for(int i = 0; i < ArrayFile.GetSize(); i++)
{
...
pmodEncrypt->DoEncrypt(iRow, strFileName, pRightInfo, strEncFile);
ArrayEncFile.Add(strEncFile);
//处理结束
FinishEncryptMod();
if (g_bStopCheckFileType)
{
return ;
}
}
}
其中myProcess是在线程中完成的,g_bStopCheckFileType是全局变量,用于标示当前的操作是否取消。我现在的问题是,当我正常处理文档进行加密并SortAccountEncFile时,isize的值为0,因为m_mapAccountEncFile只是SortAccountEncFile的一个输出参数而已,前面也clear了,但是如果是在程序运行过程中,点击取消,我发现isize就变成了13,但是事实上我在Encrypt中根本没有对m_mapAccountEncFile操作,所以应该是0才对,并且调试时使用m_mapAccountEncFile.clear()就会出现非法访问,请高手指点这是什么原因?
typedef struct AccountEncFileList
{
CString arrayUserAccount;
CString arrayUserName;
list<CString> listEncFile;
}ACCOUNT_ENCFILE;
map<CString, ACCOUNT_ENCFILE> m_mapAccountEncFile;
在CProcess.cpp中使用
void CProcess::myProcess()
{
//初始化保存用户和对应加密文档的列表
m_mapAccountEncFile.clear();
for(int iR= 0; iR<4; iR++)
{
if ( g_bStopCheckFileType)
{
break;
}
....
pEncrypt.Encrypt(iR, m_ArrayFileName, ArrayEncFile, m_RightInfo, m_dlgProgress, g_bStopCheckFileType);
int isize = m_mapAccountEncFile.size();
SortAccountEncFile(userInfo, ArrayEncFile, m_mapAccountEncFile);
...
}
}
Encrypt是自定义的一个加密类中的函数,在Encrypt中
void CEncryptCtrl::Encrypt(int iRow, CStringArray & ArrayFile, CStringArray & ArrayEncFile, CRightInfo pRightInfo, CProgressDlg &dlgProgress, BOOL bStop)
{
for(int i = 0; i < ArrayFile.GetSize(); i++)
{
...
pmodEncrypt->DoEncrypt(iRow, strFileName, pRightInfo, strEncFile);
ArrayEncFile.Add(strEncFile);
//处理结束
FinishEncryptMod();
if (g_bStopCheckFileType)
{
return ;
}
}
}
其中myProcess是在线程中完成的,g_bStopCheckFileType是全局变量,用于标示当前的操作是否取消。我现在的问题是,当我正常处理文档进行加密并SortAccountEncFile时,isize的值为0,因为m_mapAccountEncFile只是SortAccountEncFile的一个输出参数而已,前面也clear了,但是如果是在程序运行过程中,点击取消,我发现isize就变成了13,但是事实上我在Encrypt中根本没有对m_mapAccountEncFile操作,所以应该是0才对,并且调试时使用m_mapAccountEncFile.clear()就会出现非法访问,请高手指点这是什么原因?
另外map不是线程安全的,在m_mapAccountEncFile[key]时会有个堆查找的操作,此时另外一个线程如果有删除操作就会造成访问冲突(常常是因为迭代器失效)。
=====
你应该贴跟m_mapAccountEncFile相关的代码,贴那个加密函数完全没有指导意义嘛~
if (g_bStopCheckFileType)
{
return ;
} 那样也会安插一个元素?
那我要想往map中插入元素,安全的方法是怎么样的呢?
线程安全的话,map的插入、移除操作要手动加锁才行。
void CProcess::SortAccountEncFile(USER_INFO & UserInfo, CStringArray &ArrayEncFile, map<CString, ACCOUNT_ENCFILE> & mapAccountEncFile)
{
CString strAAccount = "";
int AccountCount = UserInfo.arrayUserAccount.GetSize();
int NameCount = UserInfo.arrayUserName.GetSize(); int g = mapAccountEncFile.size(); /////此时g已经变成13了
if ( g_bStopCheckFileType)
{
return ;
} ACCOUNT_ENCFILE AccountEncFile, newAccountEncFile;
for(int i = 0; i < AccountCount; i++)
{
strAAccount = UserInfo.arrayUserAccount[i]; map<CString, ACCOUNT_ENCFILE>::iterator it = mapAccountEncFile.begin(); while (it != mapAccountEncFile.end())
{
AccountEncFile = (ACCOUNT_ENCFILE)((*it).second); //如果AccountEncFileList列表中存在该用户,则直接将对应的加密后文档加入EncFileList列表
if(strAAccount == AccountEncFile.arrayUserAccount)
{
if(i < NameCount)
{
newAccountEncFile.arrayUserName = UserInfo.arrayUserName[i];
}
newAccountEncFile = AccountEncFile;
break;
} it++;
}
//如果AccountEncFileList列表中不存在该用户,则在AccountEncFileList列表尾部增加该用户及对应的EncFileList列表
if(it == mapAccountEncFile.end())
{
newAccountEncFile.arrayUserAccount = strAAccount;
if(i < NameCount)
{
newAccountEncFile.arrayUserName = UserInfo.arrayUserName[i];
} m_dwAllUserCounts ++;
} InsertAccountEncFile(newAccountEncFile, ArrayEncFile, mapAccountEncFile);
}
}
void CProcess::InsertAccountEncFile(ACCOUNT_ENCFILE & AccountEncFile, CStringArray & arrayEncFile, map<CString, ACCOUNT_ENCFILE> & mapAccountEncFile)
{
AddEncFile(AccountEncFile, arrayEncFile);
mapAccountEncFile[AccountEncFile.arrayUserAccount] = AccountEncFile;
}
设计map的操作都在这里了,是不是我在判断Key是否存在时的方法不对?
你的clear在循环外面的,如果循环第二遍的话,你的map在第一个循环里面可能就已经改变了。typedef struct AccountEncFileList
{
CString arrayUserAccount;
CString arrayUserName;
list <CString> listEncFile;
}ACCOUNT_ENCFILE;
map <CString, ACCOUNT_ENCFILE> m_mapAccountEncFile;
void CProcess::myProcess()
{
m_mapAccountEncFile.clear(); //你的清理工作只清理了一次,而下面是4次的循环
for(int iR= 0; iR <4; iR++)
{
if ( g_bStopCheckFileType)
{
break;
}
....
pEncrypt.Encrypt(iR, m_ArrayFileName, ArrayEncFile, m_RightInfo, m_dlgProgress, g_bStopCheckFileType);
int isize = m_mapAccountEncFile.size(); //如果第一个循环改变了容器大小,那么iR>0的时候这里肯定就不是0了,传进去肯定也不是0了。
SortAccountEncFile(userInfo, ArrayEncFile, m_mapAccountEncFile);
...
}
} void CProcess::SortAccountEncFile(USER_INFO & UserInfo, CStringArray &ArrayEncFile, map <CString, ACCOUNT_ENCFILE> & mapAccountEncFile)
{
CString strAAccount = "";
int AccountCount = UserInfo.arrayUserAccount.GetSize();
int NameCount = UserInfo.arrayUserName.GetSize(); int g = mapAccountEncFile.size(); /////此时g已经变成13了 ==>应该是到了循环的第二次了
if ( g_bStopCheckFileType)
{
return ;
} ACCOUNT_ENCFILE AccountEncFile, newAccountEncFile;
//另外你查找的算法感觉很麻烦,但对你的业务处理不太清楚,
//map查找可以用map.find(key)查找,返回迭代器,
//用你比较的字符串做key, 速度也快,也没那么麻烦了
for(int i = 0; i < AccountCount; i++)
{
strAAccount = UserInfo.arrayUserAccount[i]; map <CString, ACCOUNT_ENCFILE> ::iterator it = mapAccountEncFile.begin();
//你要保证在循环结束之前没有其他线程对map插入删除,否则可能迭代器失效异常。
while (it != mapAccountEncFile.end())
{
AccountEncFile = (ACCOUNT_ENCFILE)((*it).second); if(strAAccount == AccountEncFile.arrayUserAccount)
{
if(i < NameCount)
{
newAccountEncFile.arrayUserName = UserInfo.arrayUserName[i];
}
newAccountEncFile = AccountEncFile;
break;
} it++;
}
if(it == mapAccountEncFile.end())
{
newAccountEncFile.arrayUserAccount = strAAccount;
if(i < NameCount)
{
newAccountEncFile.arrayUserName = UserInfo.arrayUserName[i];
} m_dwAllUserCounts ++;
} InsertAccountEncFile(newAccountEncFile, ArrayEncFile, mapAccountEncFile);
}
}
void CProcess::InsertAccountEncFile(ACCOUNT_ENCFILE & AccountEncFile, CStringArray & arrayEncFile, map <CString, ACCOUNT_ENCFILE> & mapAccountEncFile)
{
AddEncFile(AccountEncFile, arrayEncFile);
mapAccountEncFile[AccountEncFile.arrayUserAccount] = AccountEncFile;
}