分享

使用ADO,最后关闭_ConnectionPtr,_RecordsetPtr后,析构出错,请教高手

 9loong 2012-04-17
2008-12-30 15:40
楼主boilingwater() 2003-02-14 16:21:45 在 VC/MFC / 数据库 提问

定义了Manager作为全局变量,其中包含一个_ConnectionPtr和一个_RecordsetPtr成员变量.
执行了3步操作
1 m_pLConnect.CreateInstance("ADODB.Connection");
m_pLRecordset.CreateInstance("ADODB.Recordset");

2 m_pLConnect->Open(....);
m_pLRecordset->Open(...);

3 m_pLConnect->Close();
m_pLRecordset->Close();

分别在3个函数中调用.
最后析构Manager时(析构函数里什么也没有),出现错误,指向
void _Release() throw()
{
if (m_pInterface != NULL) {
m_pInterface->Release(); //这里
}
}

m_pInterface 不为0.

我想ADO的connect和recordset不需要release吧,也不需要设为NULL吧?
哪这个错误是怎么产生的呢?
问题点数:100、回复次数:23Top

1 楼boilingwater() 回复于 2003-02-14 16:24:44 得分 0

对了,中间执行的操作都很正常.Top

2 楼Aizz(Nova) 回复于 2003-02-14 16:40:46 得分 0

试试3的顺序反一下:
m_pLRecordset->Close();
m_pLConnect->Close();
Top

3 楼boilingwater() 回复于 2003-02-14 17:22:03 得分 0

Aizz(Nova),我试过了,还是不行.Top

4 楼boilingwater() 回复于 2003-02-14 17:25:06 得分 0

这次我连open都没有,只有createinstance,析构时还出错Top

5 楼Aizz(Nova) 回复于 2003-02-14 17:29:52 得分 0

没遇见过,错误信息是什么?Top

6 楼boilingwater() 回复于 2003-02-14 17:31:09 得分 0

抱歉,先离开,明天晚上再来
Top

7 楼samyoung(sam) 回复于 2003-02-14 17:34:17 得分 0

_ConnectionPtr不需要每次用了都close,这个只需要在程序结束的时候close一下就行了,推荐这样
//程序退出时关闭与数据源的连接
if(m_pConnection)
{
m_pConnection->Close();//关闭并释放与数据库的连接
}

同时,建议将_ConnectionPtr m_pLConnect放在App类里面定义,在InitInstance函数中初始化,创建实体和打开,在ExitInstance中close。


Top

8 楼boilingwater() 回复于 2003-02-17 14:10:06 得分 0

_ConnectionPtr我是只close了一次.
因为需要所以不能将_ConnectionPtr m_pLConnect放在App类里面定义,在InitInstance函数中初始化,创建实体和打开,在ExitInstance中close。
另外,提示错误就是UNHANDLED EXCEPTION.就指向这里了.
void _Release() throw()
{
if (m_pInterface != NULL) {
m_pInterface->Release(); //这里
}
}
Top

9 楼boilingwater() 回复于 2003-02-17 15:14:51 得分 0

那位高手能给我讲解一下ado的connect和recordset的使用过程中,内存是如何分配的?哪里申请,哪里释放,哪里设为NULL?Top

10 楼hany3000(倾城一片) 回复于 2003-02-17 17:06:39 得分 0

好像不要用哪个release函数,我用哪个也出错的,
这样行不行
m_pInterface->Close();
m_pInterface=NULL;Top

11 楼boilingwater() 回复于 2003-02-17 17:10:18 得分 0

好像也不需要=NULL吧?Top

12 楼zzyx(菜农) 回复于 2003-02-17 17:28:27 得分 0

COM组件线程的公寓模型问题?
STA、MTA?
如果你进行了跨线程的访问,看看这方面的情况吧Top

13 楼boilingwater() 回复于 2003-02-18 09:07:25 得分 0

拜托 zzyx(菜农)再说的详细点好吗?

这个问题,其实我自己已经解决了.我发现
1 m_pLConnect.CreateInstance("ADODB.Connection");
m_pLRecordset.CreateInstance("ADODB.Recordset");
放置的位置不同,结果就会不同.可是我没有跨线程访问呀.

这两个问题解答了都有分相送,还可以再加分.

那位高手能给我讲解一下ado的connect和recordset的使用过程中,内存是如何分配的?哪里申请,哪里释放,哪里设为NULL?

Top

14 楼Aizz(Nova) 回复于 2003-02-18 11:28:17 得分 0

>>放置的位置不同,结果就会不同.
楼主可以详细说说是怎么个不同法吗?

我在2000里试了一下,只要Close()的顺序正确,是不会出错的。CreateInstance()的顺序应该不会有影响。
智能指针_RecordsetPtr和_ConnectionPtr在超出作用域是会自动释放的,也就是说指针在CreateInstance()的时候 分配内存,在作用域外释放,所以自己调用Release()并不是必需的,不过调用也不会出错,而设为NULL是完全可以不用的。
Top

15 楼Aizz(Nova) 回复于 2003-02-18 15:35:49 得分 0

上面“CreateInstance()的时候分配内存”这句应该是“建立接口的引用”。Top

16 楼zzyx(菜农) 回复于 2003-02-18 19:50:40 得分 0

我还是有点怀疑你有跨线程的情况。
因为很显然,用最普通的方式使用_ConnectionPtr来完成工作不会有任何问题,放到类里也不会有影响。

试验用参数COINIT_MULTITHREADED 或COINIT_APARTMENTTHREADED 调用
CoInitializeEx来初始化COM看看。

Top

17 楼boilingwater() 回复于 2003-02-19 09:46:26 得分 0

哪我的指针不会超出作用域,除非推出程序.因为它是在一个全局变量里.

extern CMyParam MyParam; //MyParam里有connect和recordset智能指针
我在子对话框初始化时,用CreateInstance(),并直接Open(),在子对话框OnCancel时,用close().这样一切都正常,即使再调用子对话框,也正常.
可我也不明白,这样多次CreateInstance()没有问题吗?

如果把CreateInstance()放到主对话框的初始化中,在子对话框初始化时Open(),
在子对话框OnCancel时,用close().不管在何处,用不用release(),赋不赋成NULL,最后推出程序,MyParam析构时都会出错.
就是我最先提出的那个错误.

提示错误就是UNHANDLED EXCEPTION.就指向这里了.
void _Release() throw()
{
if (m_pInterface != NULL) {
m_pInterface->Release(); //这里
}
}
Top

18 楼lwg7603(刑满释放人员) 回复于 2003-02-19 10:18:41 得分 50

COM调用越界了(即在CoUninitialize()调用完成后,再调用COM的方法)因为全局变量的析构在最 后才调用!检查你的 CoInitialize(NULL)和CoUninitialize()调用,你在调用CoUninitialize()的位置设断点,在 ~CMyParam()内部(任何语句处)也设断点.然后推出程序,看看程序先运行到哪个断点处就明白了~~~

解决方法:修改程序结构 ,不要在全局对象中使用智能指针~


Top

19 楼lwg7603(刑满释放人员) 回复于 2003-02-19 11:09:42 得分 0

解决方法:修改程序结构 ,不要在全局对象中使用智能指针~,,或在CoUninitialize()调用之前,调用m_pLRecordset.Release(),m_pLConnect->
Release();
Top

20 楼boilingwater() 回复于 2003-02-19 12:12:55 得分 0

我加了release也不行啊.
而且我用的是AfxOleInit().不用CoUninitialize()啊.Top

21 楼lwg7603(刑满释放人员) 回复于 2003-02-19 13:15:35 得分 0

在CxxxAPP类的ExitInstance函数中调用release试试?Top

22 楼zzyx(菜农) 回复于 2003-02-19 14:01:51 得分 20

看来 lwg7603(刑满释放人员) 是正确。

可以这样实现:
增加Init,和Uninit函数,其中分别完成创建对象,析构对象的操作。
然后在代码中需要的地方分别调用。这样你就能把你的对象控制在COM作用范围内存在了。Top

23 楼Aizz(Nova) 回复于 2003-02-19 15:51:35 得分 30

我是在类的构造函数CoInitialize(),析构函数CoUninitialize(),并且没用Release(),没有出现错误(Win2000环境)。

另外,全局变量肯定在InitInstance()之前构造,而在ExitInstance()之后析构,所以在上面两个函数里面初始释放COM环境应该 是不行的;就算在析构函数中CoUninitialize(),一样也是在接口指针释放之前(除非显示调用Release())释放COM环境,庆幸的是 在2000中这样没什么问题(不知道98会不会报错)。

(###)

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多