拷贝函数出错(不是每次都会出错,偶尔会出错一次)实在不知道原因,
BOOL CPublicFun::CopyChar(char *p1, const char *ps, int nMax)
{
BOOL bRe = TRUE;
int nlen = 0;
try {
nlen = strlen(ps);
if (nlen > nMax) nlen = nMax;
memcpy(p1, ps, nMax); // 这句出错,
p1[nlen] = '\0';
} catch (...) {
CString str;
str.Format("%d, %d, %s, %s", nlen, nMax, p1, ps);
AfxMessageBox(str);
bRe = FALSE;
}
return bRe;
}
nMax=30, sizeof(p1)=31,sizeof(ps) < 20,
出错那句由于不小心将nlen写成了nMax,但即使这样也不应该出错啊。只是读越界,并非写越界。
请各位帮忙指点一下这是为什么??
BOOL CPublicFun::CopyChar(char *p1, const char *ps, int nMax)
{
BOOL bRe = TRUE;
int nlen = 0;
try {
nlen = strlen(ps);
if (nlen > nMax) nlen = nMax;
memcpy(p1, ps, nMax); // 这句出错,
p1[nlen] = '\0';
} catch (...) {
CString str;
str.Format("%d, %d, %s, %s", nlen, nMax, p1, ps);
AfxMessageBox(str);
bRe = FALSE;
}
return bRe;
}
nMax=30, sizeof(p1)=31,sizeof(ps) < 20,
出错那句由于不小心将nlen写成了nMax,但即使这样也不应该出错啊。只是读越界,并非写越界。
请各位帮忙指点一下这是为什么??
还有。出错之后,在catch中看到的状态居然全都是对的。
ps必须=<sizeof(p1)
p1必须不能指向完全属于自已的空间
{
if(!strDest || !strSour || !uMax)
return false; while(*strSour && uMax)
{
*strDest++ = *strSour ++;
uMax --;
} if(*strSour)
{
*--strDest = _T('\0');
return false;
}
else
return true;
}
ps必须= <sizeof(p1)
p1必须不能指向完全属于自已的空间
{
BOOL bRe = TRUE;
int nlen = 0;
try {
nlen = strlen(ps);
if (nlen > nMax) nlen = nMax;
if (nMax > strlen(p1)) nMax = strlen(p1);//加一句!!!!!!!!!!!
memcpy(p1, ps, nMax); // 这句出错,
p1[nlen] = '\0';
} catch (...) {
CString str;
str.Format("%d, %d, %s, %s", nlen, nMax, p1, ps);
AfxMessageBox(str);
bRe = FALSE;
}
return bRe;
}
sizeof(p1)是定义为31的数组,nMax是传的一个常量,值为30,我想这想应该是满足的吧。因为ps的实际长度总是小于nMax的,而我每次都让它拷的nMax个。这个会不会有关系
{
BOOL bRe = TRUE;
int nlen = 0;
try {
if (nMax > strlen(p1)) nMax = strlen(p1);//加一句!!!!!!!!!!! 前面写错了,应加在这儿
nlen = strlen(ps);
if (nlen > nMax) nlen = nMax;
memcpy(p1, ps, nMax); // 这句出错,
p1[nlen] = '\0';
} catch (...) {
CString str;
str.Format("%d, %d, %s, %s", nlen, nMax, p1, ps);
AfxMessageBox(str);
bRe = FALSE;
}
return bRe;
}
是这个问题,
应该是memcpy(p1, ps, nlen ); // 这句出错,
nlen = strlen(ps);
if (nlen < nMax)
nMax = nlen;
当然其实memcpy就用nlen作大小参数也可以。
if (nMax > strlen(p1)) nMax = strlen(p1);//加一句!!!!!!!!!!! 前面写错了,应加在这儿
这句不能加,p1是被初始化为空的,加上这句一个字符都拷不进去了。
{
try
{
if(strlen(ps)>strlen(p1))
memcpy(p1, ps, strlen(p1));
else
memcpy(p1, ps, strlen(ps));
}
catch (...)
{
return false;
}
return true;
}
memcpy(p1, ps, nMax);这样写会有错误。可能是些什么样的原因引起的,而且还不能是每次都会引起异常的那种。
我实际应用中ps长度绝对不会超过20,p1是个31的数组,nMax是个定值30。
CString str = "sfdsfd";
CString str1 = "sfdsfsfdsfsdfsdfsdfdsfsdfsdfsdfsdfd";
CString str2 = "sfdsfsdfdsfdffffffffffffffffffffffd";
CopyChar(c, (LPTSTR)(LPCTSTR)str, 30);
CopyChar(c, (LPTSTR)(LPCTSTR)str1, 30);
CopyChar(c, (LPTSTR)(LPCTSTR)str2, 30);ps小于30之后没事,我觉得很有可能ps之后的字符是不可读的。
Release下面不会有事
ST_MODULE stInfo; strInfo.Format("Select * from BoardType where DeviceType=%d order by Code", theApp.m_nDeviceType);
if (pDB == NULL) {
pDB = &m_Myado;
}
if (pDB->DoSQL(strInfo)) {
while (!pDB->m_Rst->adoEOF) {
strInfo = pDB->GetStr(2); // 名称
// TRACE("\n%s", strInfo);
stInfo.uType = (UCHAR)pDB->GetLongField(4); // 类型代码
if (!m_PubProc.CopyChar(stInfo.Name, (LPTSTR)(LPCTSTR)strInfo)) {
AfxMessageBox(strInfo);
} // 添加取数据存储区
SetType(&stInfo); memset(&stInfo, 0, sizeof(ST_MODULE));
pDB->m_Rst->MoveNext();
}
pDB->m_Rst->Close();
}if (!m_PubProc.CopyChar(stInfo.Name, (LPTSTR)(LPCTSTR)strInfo))
就是调用的那个拷贝函数
CString中的字符串是用new分配的内存,当字符串长度为20时,分配的内存长度通常是21,当执行memcpy时,由于指定的nMax是30,所以要复制30字节的数据,这就需要访问超过第21个字符之后的内存,也就是越界了,如果所访问的内存已经分配给了其它地方,访问就不会有问题,如果所访问的内存没有分配(这里的分配指的是虚拟内存页),就会产生读异常。这种内存越界引起读异常发生的几率不高。