一个如此简单的ado测试程序居然有内存泄漏,请大虾出手!

Un1 2010-04-21 03:31:35
一天内存使用从8M上升到32M, ado已经更新到最新版本,vc win32 程序全部代码:


#include "stdafx.h"
#include "stdio.h"

int APIENTRY WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
// TODO: Place code here.

CoInitialize(NULL);

_ConnectionPtr pConn("ADODB.Connection");
pConn->Open("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=\"scd.mdb\"", "", "", 0);

MessageBox(NULL, "Start testing", NULL, 0);

long bytes = 1;
long duration = 1;
char ip[16];
strcpy(ip, "1.1.1.1");

long sec = 1;
char path[256];
strcpy(path, "\\path1\\path2");


char id[25];
strcpy(id, "abcdefgh-123456789012345");

char d[20];

while(1){

SYSTEMTIME st;
GetLocalTime(&st);
sprintf(d, "%04d-%02d-%02d %02d:%02d:%02d", st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond);

char sql[128];
sprintf(sql, "select * from bills where time='%s' and id='%s'", d, id);

try{
_RecordsetPtr rs("ADODB.Recordset");
rs->Open(sql, _variant_t((IDispatch *)pConn, true), adOpenForwardOnly, adLockOptimistic, adCmdText);

if(rs->adoEOF){
rs->AddNew();
rs->PutCollect("time", d);
rs->PutCollect("id", id);
}
rs->PutCollect("bytes", bytes);
rs->PutCollect("duration", duration);
rs->PutCollect("ip", ip);
rs->PutCollect("sec", sec);
rs->PutCollect("path", path);

rs->Update();
rs->Close();
}catch(...){};

Sleep(1000);

FILE *fp = fopen("stop.txt", "rb");
if(fp){
fclose(fp);
break;
}
}

pConn = NULL;

CoUninitialize();

MessageBox(NULL, "App stopped!", NULL, 0);
return 0;
}
...全文
196 点赞 收藏 20
写回复
20 条回复
Un1 2010年04月29日
没办法了,只好定时释放所有数据库变量再重新打开了。
回复 点赞
公共马甲0315 2010年04月23日
lz用的是mdb呀,mdb文件要经常压缩一下的,不然会变得很大而且还会占用一些无用空间的。我也不知道为什么,但是每次操作完mdb文件后,它就会变大而绝不会变小的,不管是删除还是修改记录。这时候就得压缩一下子。数据库文件本身的大小也会影响使用的内存资源的
回复 点赞
路人乙2019 2010年04月22日
pConn->Close();
pConn->Release();
pConn = NULL;
回复 点赞
路人乙2019 2010年04月22日

pConn->Close();
pConn.Release();
pConn = NULL;
回复 点赞
康斯坦汀 2010年04月22日
ADO本身的问题也说不定。
ADO的目的是让VB等脚本语言访问数据库,本来就不是给C++
用的,你非要用C++与ADO的方式,本身就不对。

建议换成OLEDB。
回复 点赞
sgzwiz 2010年04月22日
[Quote=引用 16 楼 yaozhiyong110 的回复:]
数据库所在的机子上 本来内存就会一直涨的
这是数据库的策略 随着你查询次数增多而增加 但到达
一个最大值便不在增长 你可以修改这个值 在数据库设置里面
这不是程序的问题 是数据库处理业务的问题[/Quote]
up
回复 点赞
yaozhiyong110 2010年04月22日
你自己把 数据库的内存值设小或者多运行一段时间 测试下不就知道了????
回复 点赞
yaozhiyong110 2010年04月22日
[Quote=引用 15 楼 un1 的回复:]
rs是在try后面的{}块中申明的,所以在执行rs->Close()后,编译器就自动执行rs->Release了,已经释放了。用F11单步跟踪可以看到。

现在就是要解决rs被释放后,占用的内存依然增长的问题,否则这样的代码无法在服务器中使用。服务器是常年不开关机的。
[/Quote]

我已经说了

数据库所在的机子上 本来内存就会一直涨的
这是数据库的策略 随着你查询次数增多而增加 但到达
一个最大值便不在增长 你可以修改这个值 在数据库设置里面
这不是程序的问题 是数据库处理业务的问题
回复 点赞
Un1 2010年04月22日
rs是在try后面的{}块中申明的,所以在执行rs->Close()后,编译器就自动执行rs->Release了,已经释放了。用F11单步跟踪可以看到。

现在就是要解决rs被释放后,占用的内存依然增长的问题,否则这样的代码无法在服务器中使用。服务器是常年不开关机的。



回复 点赞
yaozhiyong110 2010年04月22日
[Quote=引用 12 楼 un1 的回复:]
各位回答pConn->Close, pConn->Release的同学注意了,我说的内存泄漏是指程序运行中占用内存不断增长,不是说退出后发现有内存没有释放。实际上,出现增长时,还在运行while循环,并没有运行到需要释放pConn的代码。
[/Quote]

严格上说 这不是内存泄漏 要让它不涨 只有自己去管理数据库的内存池 不过其实没这个必要
如果对内存池管理很简单 那数据库的开发公司早就会实现相应的工具了!
回复 点赞
yaozhiyong110 2010年04月22日
while(1){

SYSTEMTIME st;
GetLocalTime(&st);
sprintf(d, "%04d-%02d-%02d %02d:%02d:%02d", st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond);

char sql[128];
sprintf(sql, "select * from bills where time='%s' and id='%s'", d, id);

try{
_RecordsetPtr rs("ADODB.Recordset");
rs->Open(sql, _variant_t((IDispatch *)pConn, true), adOpenForwardOnly, adLockOptimistic, adCmdText);

if(rs->adoEOF){
rs->AddNew();
rs->PutCollect("time", d);
rs->PutCollect("id", id);
}
rs->PutCollect("bytes", bytes);
rs->PutCollect("duration", duration);
rs->PutCollect("ip", ip);
rs->PutCollect("sec", sec);
rs->PutCollect("path", path);

rs->Update();
rs->Close();
}catch(...){};

你每次查询 都要将游标释放一次 这才正确
其次 数据库所在的机子上 本来内存就会一直涨的
这是数据库的策略 随着你查询次数增多而增加 但到达
一个最大值便不在增长 你可以修改这个值 在数据库设置里面
这不是程序的问题 是数据库处理业务的问题
回复 点赞
Un1 2010年04月22日
各位回答pConn->Close, pConn->Release的同学注意了,我说的内存泄漏是指程序运行中占用内存不断增长,不是说退出后发现有内存没有释放。实际上,出现增长时,还在运行while循环,并没有运行到需要释放pConn的代码。
回复 点赞
Un1 2010年04月21日
没有其他代码了...

[Quote=引用 7 楼 qiangorqiang 的回复:]
从代码看没有问题。
pConn是智能指针,可以不需要调用Release()函数。
是否是其他地方的代码导致的。
[/Quote]
回复 点赞
qiangorqiang 2010年04月21日
从代码看没有问题。
pConn是智能指针,可以不需要调用Release()函数。
是否是其他地方的代码导致的。
回复 点赞
尹成 2010年04月21日
注意清理对象

pConn = NULL;
-->
pConn->Close();
pConn.Release();
回复 点赞
buptzwp 2010年04月21日
[Quote=引用 4 楼 zsx1234567 的回复:]

飘过!!问个问题,内存泄露有什么危害吗??学习!!
[/Quote]
这个还用想嘛,内存就那么多。
回复 点赞
HonestManXin 2010年04月21日
飘过!!问个问题,内存泄露有什么危害吗??学习!!
回复 点赞
zyq5945 2010年04月21日
pConn = NULL;
-->
pConn->Close();
pConn.Release();
回复 点赞
klkvc386 2010年04月21日
Up.......
回复 点赞
King030609 2010年04月21日
默哀中…………
回复 点赞
发动态
发帖子
数据库
创建于2007-09-28

3444

社区成员

3.9w+

社区内容

VC/MFC 数据库
社区公告
暂无公告