一个如此简单的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;
}
...全文
271 20 打赏 收藏 转发到动态 举报
写回复
用AI写文章
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
  • 打赏
  • 举报
回复
默哀中…………

4,011

社区成员

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

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