又是内存问题,各位高手救命啊!高分相谢!

Wanix 2010-05-01 02:15:16
调用下面的操作数据库函数时,如果当时数据库断开了,会走异常分支A,在异常分支中程序正常,ShowTip和WriteLog运行正常,当函数return返回时报Unhandled exception in TEST.exe (MFC42D.DLL): 0xC0000005: Access Violation。
经过调试跟踪,发现在C:\Program Files\Microsoft Visual Studio\VC98\MFC\Include\AFX.INL中的
_AFX_INLINE CStringData* CString::GetData() const
{ ASSERT(m_pchData != NULL); return ((CStringData*)m_pchData)-1; }
里报的,已经搞了好几个晚上了,哪位高人给指点一下呀?!??!

bool CTestDlg::InsertCurrProperty(CString strA, CString strB,
CString strC, CString strD, CString strE,
CString strF, CString strG,
CString strH, CString &strI)
{
char szSql[256];
char aczA[64];
char aczB[32];
char aczC[16];
char aczD[16];
char aczF[32];
char aczG[32];
char aczH[64];
char aczSystemTime[32];

SYSTEMTIME stSysTime;
bool bRet = true;

memset(szSql, 0, sizeof(szSql));
memset(aczA, 0, sizeof(aczA));
memset(aczB, 0, sizeof(aczB));
memset(aczC, 0, sizeof(aczC));
memset(aczD, 0, sizeof(aczD));
memset(aczF, 0, sizeof(aczF));
memset(aczG, 0, sizeof(aczG));
memset(aczH, 0, sizeof(aczH));
memset(aczSystemTime, 0, sizeof(aczSystemTime));

strcpy(aczA, strA);
strcpy(aczB, strB);
strcpy(aczC, strC);
strcpy(aczD, strD);
strcpy(aczF, strF);
strcpy(aczG, strG);
strcpy(aczH, strH);

sprintf( szSql, "SELECT * FROM TEST WHERE A='%s'", strA );

CTime time = CTime::GetCurrentTime();
time.GetAsSystemTime(stSysTime);
sprintf(aczSystemTime, "%d-%02d-%02d %02d:%02d:%02d.%03d",
stSysTime.wYear, stSysTime.wMonth, stSysTime.wDay,
stSysTime.wHour, stSysTime.wMinute, stSysTime.wSecond,
stSysTime.wMilliseconds);

try
{
//互斥访问
WaitForSingleObject( gPublicEvent, INFINITE );

// 开始事务
//m_pConnection->BeginTrans();

//打开数据表
HRESULT hr = m_pRecordset->Open( szSql,
m_pConnection.GetInterfacePtr(), // Get Link Libary IDispatch Pointer
adOpenDynamic,
adLockOptimistic,
adCmdText
);
if (!SUCCEEDED(hr))
{
//事务回退
//m_pConnection->RollbackTrans();

// 置为已通知
SetEvent(gPublicEvent);

return false;
}

int nCount = m_pRecordset->GetRecordCount();
if (nCount > 1)
{
// 置为已通知
SetEvent(gPublicEvent);

return false;
}

_variant_t var, varget;

//找到
if ( !m_pRecordset->adoEOF )
{
/*先获取上次的值*/
varget = m_pRecordset->GetCollect("F");
strI = (LPCSTR)_bstr_t(varget);

/*修改记录*/
//m_pRecordset->PutCollect("A", _variant_t(strA));
m_pRecordset->PutCollect("RouterID", _variant_t(strB));
var.iVal = atoi(strC);
m_pRecordset->PutCollect("C", var.iVal);
var.iVal = 0;
m_pRecordset->PutCollect("E", var.iVal);
var.iVal = atoi(strD);
m_pRecordset->PutCollect("D", var.iVal);
m_pRecordset->PutCollect("F", _variant_t(strF));
m_pRecordset->PutCollect("G", _variant_t(strG));
m_pRecordset->PutCollect("SystemTime", _variant_t(aczSystemTime));
m_pRecordset->PutCollect("FirstH", _variant_t(strH));
/*更新*/
m_pRecordset->Update();
}

//关闭记录集
m_pRecordset->Close();

// 置为已通知
SetEvent(gPublicEvent);
}
catch(_com_error *e)
{
bRet = false;

//关闭记录集
if (m_pRecordset->State)
{
m_pRecordset->Close();
}

// 置为已通知
SetEvent(gPublicEvent);

ShowTips(TIP_FATAL, "访问数据库表TEST出现异常, 请查看日志了解详情!");
WriteLog(LEV_ERROR, "错误编号=[%08lx], 错误信息=[%s], 错误源[%s], 错误描述[%s]",
e->Error(),
e->ErrorMessage(),
(LPCSTR)e->Source(),
(LPCSTR)e->Description());

}
catch(_com_error e) -------------------------------------------异常分支A
{
bRet = false;

//关闭记录集
if (m_pRecordset->State && e.Error() != adoConnectFail)
{
m_pRecordset->Close();
}

// 置为已通知
SetEvent(gPublicEvent);

ShowTips(TIP_FATAL, "访问数据库表TEST出现异常, 请查看日志了解详情!");
WriteLog(LEV_FATAL, "错误编号=[%08lx], 错误信息=[%s], 错误源[%s], 错误描述[%s]",
e.Error(),
e.ErrorMessage(),
(LPCSTR)e.Source(),
(LPCSTR)e.Description());

}
catch (...)
{
bRet = false;

if (m_pRecordset->State)
{
m_pRecordset->Close();
}

// 置为已通知
SetEvent(gPublicEvent);

ShowTips(TIP_FATAL, "访问数据库表TEST出现异常, 请查看日志了解详情!");
}

return bRet;
}
...全文
292 17 打赏 收藏 转发到动态 举报
写回复
用AI写文章
17 条回复
切换为时间正序
请发表友善的回复…
发表回复
Wanix 2010-05-03
  • 打赏
  • 举报
回复
非常感谢楼上各位的关注和回答,目前还是没有什么大的进展。
这个程序在正常情况下可以连续运行一个月以上没有问题,这次是为了测试当数据库连接断开后进行报警才发现的,用反汇编代码跟了下,还是没有什么头绪。
Wanix 2010-05-03
  • 打赏
  • 举报
回复
各位高手,我又做了一个最简单的测试程序,如下所示
仍然在函数返回前报Unhandled exception in dbtest.exe (MFC42D.DLL): 0xC0000005: Access Violation。

谁能提供解决方法?解决后再另开新帖加100分!

代码示例:
void CDbtestDlg::OnButton1()
{
// TODO: Add your control notification handler code here
try
{
//打开数据表
HRESULT hr = m_pRecordset->Open( "SELECT * FROM t_test",
m_pConnection.GetInterfacePtr(),
adOpenDynamic,
adLockOptimistic,
adCmdText
);
if (!SUCCEEDED(hr))
{
return;
}
}
catch(_com_error &e)
{
//关闭记录集
if (m_pRecordset->State)
{
m_pRecordset->Close();
}
}
}
zyq5945 2010-05-01
  • 打赏
  • 举报
回复
另说下,捕获异常参数不是catch(_com_error *e),是_com_error &e,你可以看下我的blog里刚整理出来的这篇,不是access数据库的话就是连接字符串改下。
Wanix 2010-05-01
  • 打赏
  • 举报
回复
当数据库发生异常时,只进catch( _com_error e) 那个分支,其他分支都不进,我目前的所有变量都是在外面定义的,还是不行。
谁能说清楚异常处理时对函数调用栈会不会进行改变呀?异常处理时究竟是个什么样的内部处理机制?
dirdirdir3 2010-05-01
  • 打赏
  • 举报
回复
varget = m_pRecordset->GetCollect("F");
strI = (LPCSTR)_bstr_t(varget);


你这里需要判断
if(varget.vt!=VT_NULL)
..............
lmxmx 2010-05-01
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 mypro 的回复:]
另加一句,用winDbg调试,发现在调用CString的析构函数~CString时抛出的异常。
[/Quote]

尽量不要使用CString作为函数的参数,最好直接传入字符串指针,例如:char *pczXXX
zxdyu2009 2010-05-01
  • 打赏
  • 举报
回复
把后面两个catch去掉,试试。
zyq5945 2010-05-01
  • 打赏
  • 举报
回复
_com_error &e与_com_error e执行结果一个样子的,前一个是原来变量的一个别名,后一个是定义一个新变量,作为参数的副本。
把所有的变量定义和分配堆内存工作都放在try外面。
Wanix 2010-05-01
  • 打赏
  • 举报
回复
_com_error &e与_com_error e是一样的,只能使用其中一种,我试过了,结果是一样的。而且现在也不是入口参数是CString的问题了,我改成char *也一样,好像是catch的问题,catch过后,调用栈里的变量地址就都变了,导致函数退出时退栈访问了非法地址。现在的问题是为什么会有这样的现象?怎么可以避免?
alan001 2010-05-01
  • 打赏
  • 举报
回复
up............
尹成 2010-05-01
  • 打赏
  • 举报
回复
捕获异常参数不是catch(_com_error *e),是_com_error &e,你可以看下我的blog里刚整理出来的这篇,不是access数据库的话就是连接字符串改下
Wanix 2010-05-01
  • 打赏
  • 举报
回复
另加一句,用winDbg调试,发现在调用CString的析构函数~CString时抛出的异常。
Wanix 2010-05-01
  • 打赏
  • 举报
回复
[Quote=引用 4 楼 zyq5945 的回复:]
另说下,捕获异常参数不是catch(_com_error *e),是_com_error &e,你可以看下我的blog里刚整理出来的这篇,不是access数据库的话就是连接字符串改下。
[/Quote]
我的代码里对_com_error *e,_com_error e和...都catch了,这不会有问题的
Wanix 2010-05-01
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 dirdirdir3 的回复:]
varget = m_pRecordset->GetCollect("F");
strI = (LPCSTR)_bstr_t(varget);


你这里需要判断
if(varget.vt!=VT_NULL)
..............
[/Quote]
说得有理,这块考虑得不是很周全
Wanix 2010-05-01
  • 打赏
  • 举报
回复
我也觉得是CString参数的问题,但是为什么呢?是不是发生异常时会生产新的调用堆栈?把原来的调用堆栈给冲了?
etz2008 2010-05-01
  • 打赏
  • 举报
回复
可能是数据库连接字串
或者是SQL语句
还有就是字段名都好检查检查
我也遇到这同样的问题
Eleven 2010-05-01
  • 打赏
  • 举报
回复
你Debug下打开call back窗口,看看运行到哪个函数里抛出异常

4,011

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 数据库
社区管理员
  • 数据库
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧