4406|9

49

帖子

0

TA的资源

一粒金砂(初级)

楼主
 

CE5.0数据库问题:CeReadRecordProps()的使用与内存泄露 [复制链接]

偶对数据库操作函数不是很熟,今天看到一同事写的CeReadRecordProps()函数的使用.怀疑它产生了内存泄露,请大家帮忙分析一下,代码如下:
PBYTE pBuff;

for(j = 0; j < iRecordCount; j++)
{
  //移动记录指针
  ceOid = CeSeekDatabase(m_hDB,CEDB_SEEK_BEGINNING,j,&dwIndex);
  if(ceOid == 0)
  {
    AfxMessageBox(_T("读记录失败!!"));
    return(FALSE);
  }
  
  pBuff = 0;
  ceOid = CeReadRecordProps(m_hDB,CEDB_ALLOWREALLOC,&wProps,NULL,&(LPBYTE)pBuff,&dwRecSize);
  if(ceOid == 0)
  {
    AfxMessageBox(_T("读记录失败!!!"));
    return(FALSE);
  }
  pRecord = (PCEPROPVAL)pBuff;
  for (i = 0; i < wProps; i++)
  {
    // 数据分析
    pRecord++;
  }
}

CeReadRecordProps()函数的参数:pBuff,与CEDB_ALLOWREALLOC的使用:CeReadRecordProps()在使用了CeReadRecordProps参数时,将调用LocalAlloc()为pBuff分配内存.
现在的问题是:分配到的内存pBuff,在何时释放?及如何释放?

在网上看,大家在讨论是使用free,free[],还是LocalFree()来释放.

特别的,在代码中,强制给pBuff赋值为零的代码,使的API有可能再也找不到以前分配的内存,所以导致内存泄露.这是我的观点,大家帮忙看看,多谢!

最新回复

看这个函数 void CePimCommand(HWND hWnd, PIMTYPE ptData, UINT uDataCount, HANDLE *rghData, void *pReserved) {         if (uDataCount != 1)                 return;         CEOID oid = *(CEOID *)rghData;         CEOID db_out = 0;         HANDLE hdb = CeOpenDatabase (&db_out, L"Contacts Database", 0, 0, NULL);         if (hdb == INVALID_HANDLE_VALUE)                 return;         DWORD dwIndex = 0;         if (! CeSeekDatabase (hdb, CEDB_SEEK_CEOID, (DWORD)oid, &dwIndex))                 return;         unsigned char *lpBuff = NULL;         DWORD cBuff = 0;         CEPROPID aPropID[PHONE_NUM] = {                 PR_HOME_TELEPHONE_NUMBER_W,                 PR_HOME2_TELEPHONE_NUMBER_W,                 PR_BUSINESS_TELEPHONE_NUMBER_W,                 PR_CALLBACK_TELEPHONE_NUMBER_W,                 PR_CAR_TELEPHONE_NUMBER_W,                 PR_MOBILE_TELEPHONE_NUMBER_W,                 PR_RADIO_TELEPHONE_NUMBER_W,                 PR_PRIMARY_TELEPHONE_NUMBER_W };         WORD dwPropIDs = PHONE_NUM;         [color=#FF0000]if (! CeReadRecordProps (hdb, CEDB_ALLOWREALLOC, &dwPropIDs, aPropID, &lpBuff, &cBuff))                 return;[/color]         PhoneInfo numbers[PHONE_NUM];         memset (numbers, 0, sizeof(numbers));         CEPROPVAL *ppv = (CEPROPVAL *)lpBuff;         int iPhoneCnt = 0;         for (int i = 0 ; (i < dwPropIDs) && (iPhoneCnt < PHONE_NUM); ++i, ++ppv) {                 if (ppv->wFlags & CEDB_PROPNOTFOUND)                         continue;                 switch (ppv->propid) {                 case PR_HOME_TELEPHONE_NUMBER_W:                         wcscpy (numbers[iPhoneCnt].szPhoneType, L"h");                         break;                 case PR_HOME2_TELEPHONE_NUMBER_W:                         wcscpy (numbers[iPhoneCnt].szPhoneType, L"h2");                         break;                 case PR_BUSINESS_TELEPHONE_NUMBER_W:                         wcscpy (numbers[iPhoneCnt].szPhoneType, L"w");                         break;                 case PR_CALLBACK_TELEPHONE_NUMBER_W:                         wcscpy (numbers[iPhoneCnt].szPhoneType, L"c/back");                         break;                 case PR_CAR_TELEPHONE_NUMBER_W:                         wcscpy (numbers[iPhoneCnt].szPhoneType, L"car");                         break;                 case PR_MOBILE_TELEPHONE_NUMBER_W:                         wcscpy (numbers[iPhoneCnt].szPhoneType, L"m");                         break;                 case PR_RADIO_TELEPHONE_NUMBER_W:                         wcscpy (numbers[iPhoneCnt].szPhoneType, L"radio");                         break;                 case PR_PRIMARY_TELEPHONE_NUMBER_W:                         wcscpy (numbers[iPhoneCnt].szPhoneType, L"prim.");                         break;                 default:                         continue;                 }                 if (wcslen (ppv->val.lpwstr) >= MAX_PHONE)                         continue;                 wcscpy (numbers[iPhoneCnt].szPhone, ppv->val.lpwstr);                 ++iPhoneCnt;         }         if (iPhoneCnt < PHONE_NUM) {                 numbers[iPhoneCnt].szPhone[0] = '\0';                 numbers[iPhoneCnt].szPhoneType[0] = '\0';         }         int ndx = DialogBoxParam (ghInst, MAKEINTRESOURCE (IDD_DIALOG1), NULL, WhichDlg, (LPARAM)numbers);         if ((ndx >= 0) && (ndx < iPhoneCnt)) {                 PROCESS_INFORMATION pi;                 STARTUPINFO                si;                 memset (&pi, 0, sizeof(pi));                 memset (&si, 0, sizeof(si));                 si.cb = sizeof(si);                 DWORD bCP = CreateProcess (L"btdialer.exe", numbers[ndx].szPhone, NULL, NULL, FALSE, 0, NULL,                                         NULL, &si, &pi);                 if (bCP) {                         CloseHandle (pi.hThread);                         CloseHandle (pi.hProcess);                 }         }         return; } 复制代码  详情 回复 发表于 2010-1-8 13:11
点赞 关注

回复
举报

93

帖子

0

TA的资源

一粒金砂(中级)

沙发
 
当然,也有说不用释放的.因为代码中没有出现new/malloc等分配内存的语句.
 
 

回复

64

帖子

0

TA的资源

一粒金砂(初级)

板凳
 
用 LocalFree 来释放啊
 
 
 

回复

71

帖子

0

TA的资源

一粒金砂(初级)

4
 

  1. pBuff = 0;
  2.   ceOid = CeReadRecordProps(m_hDB,CEDB_ALLOWREALLOC,&wProps,NULL,&(LPBYTE)pBuff,&dwRecSize);
复制代码

&(LPBYTE)pBuff 0x00000000上的数据是未知的, 写数据到这个数据为地址的空间, 当然就会crash了..
 
 
 

回复

76

帖子

0

TA的资源

一粒金砂(初级)

5
 
引用 3 楼 flandy1982 的回复:
C/C++ code
pBuff=0;
  ceOid= CeReadRecordProps(m_hDB,CEDB_ALLOWREALLOC,&wProps,NULL,&(LPBYTE)pBuff,&dwRecSize);
&(LPBYTE)pBuff 0x00000000上的数据是未知的, 写数据到这个数据为地址的空间, 当然就会crash了..


哈哈...,看来你也不懂,去看看帮助吧,说的很清楚的
如果pBuff为空,API会自己分配内存.否则就没有这个问题了.

API分配内存是可以肯定的,但是什么问题释放分配的内存不清楚!
 
 
 

回复

63

帖子

0

TA的资源

一粒金砂(初级)

6
 
貌似CE中有检查内存泄露的专用工具吧,是否测试过,能得知泄露了么?

呵~~~

以前整过别人写的绘图的东东(pc下的程序),貌似CAD的一个软件,他明明动态申请了内存,但没有释放,程序未泄露,而当我加上delete后,在界面上绘图反而出现了莫名的错误,比如画个曲线,结果弧度显示不出来
 
 
 

回复

72

帖子

0

TA的资源

一粒金砂(初级)

7
 
如果pBuff为空,API会自己分配内存.否则就没有这个问题了.


有道理!!
 
 
 

回复

58

帖子

0

TA的资源

一粒金砂(初级)

8
 
引用 4 楼 91program 的回复:
引用 3 楼 flandy1982 的回复:
C/C++ code
pBuff=0;
? ceOid= CeReadRecordProps(m_hDB,CEDB_ALLOWREALLOC,&wProps,NULL,&(LPBYTE)pBuff,&dwRecSize);
&(LPBYTE)pBuff 0x00000000上的数据是未知的, 写数据到这个数据为地址的空间, 当然就会crash了..


哈哈...,看来你也不懂,去看看帮助吧,说的很清楚的
如果pBuff为空,API会自己分配内存.否则就没有这个问题了.

API分配内存是可以肯定的,但是什么问题释放分配的内存不清楚!

原来如此
微软的代码是没有释放内存的...
C:\WINCE500\PUBLIC\COMMON\OAK\DRIVERS\BLUETOOTH\SAMPLE\BTDIALP\btdialp.cxx
 
 
 

回复

72

帖子

0

TA的资源

一粒金砂(初级)

9
 
不像是这个文件中的代码
 
 
 

回复

67

帖子

0

TA的资源

一粒金砂(初级)

10
 
看这个函数

  1. void CePimCommand(HWND hWnd, PIMTYPE ptData, UINT uDataCount, HANDLE *rghData, void *pReserved) {
  2.         if (uDataCount != 1)
  3.                 return;

  4.         CEOID oid = *(CEOID *)rghData;

  5.         CEOID db_out = 0;

  6.         HANDLE hdb = CeOpenDatabase (&db_out, L"Contacts Database", 0, 0, NULL);
  7.         if (hdb == INVALID_HANDLE_VALUE)
  8.                 return;

  9.         DWORD dwIndex = 0;

  10.         if (! CeSeekDatabase (hdb, CEDB_SEEK_CEOID, (DWORD)oid, &dwIndex))
  11.                 return;

  12.         unsigned char *lpBuff = NULL;
  13.         DWORD cBuff = 0;

  14.         CEPROPID aPropID[PHONE_NUM] = {
  15.                 PR_HOME_TELEPHONE_NUMBER_W,
  16.                 PR_HOME2_TELEPHONE_NUMBER_W,
  17.                 PR_BUSINESS_TELEPHONE_NUMBER_W,
  18.                 PR_CALLBACK_TELEPHONE_NUMBER_W,
  19.                 PR_CAR_TELEPHONE_NUMBER_W,
  20.                 PR_MOBILE_TELEPHONE_NUMBER_W,
  21.                 PR_RADIO_TELEPHONE_NUMBER_W,
  22.                 PR_PRIMARY_TELEPHONE_NUMBER_W };

  23.         WORD dwPropIDs = PHONE_NUM;

  24.         [color=#FF0000]if (! CeReadRecordProps (hdb, CEDB_ALLOWREALLOC, &dwPropIDs, aPropID, &lpBuff, &cBuff))
  25.                 return;[/color]
  26.         PhoneInfo numbers[PHONE_NUM];

  27.         memset (numbers, 0, sizeof(numbers));
  28.         CEPROPVAL *ppv = (CEPROPVAL *)lpBuff;

  29.         int iPhoneCnt = 0;

  30.         for (int i = 0 ; (i < dwPropIDs) && (iPhoneCnt < PHONE_NUM); ++i, ++ppv) {
  31.                 if (ppv->wFlags & CEDB_PROPNOTFOUND)
  32.                         continue;

  33.                 switch (ppv->propid) {
  34.                 case PR_HOME_TELEPHONE_NUMBER_W:
  35.                         wcscpy (numbers[iPhoneCnt].szPhoneType, L"h");
  36.                         break;
  37.                 case PR_HOME2_TELEPHONE_NUMBER_W:
  38.                         wcscpy (numbers[iPhoneCnt].szPhoneType, L"h2");
  39.                         break;
  40.                 case PR_BUSINESS_TELEPHONE_NUMBER_W:
  41.                         wcscpy (numbers[iPhoneCnt].szPhoneType, L"w");
  42.                         break;
  43.                 case PR_CALLBACK_TELEPHONE_NUMBER_W:
  44.                         wcscpy (numbers[iPhoneCnt].szPhoneType, L"c/back");
  45.                         break;
  46.                 case PR_CAR_TELEPHONE_NUMBER_W:
  47.                         wcscpy (numbers[iPhoneCnt].szPhoneType, L"car");
  48.                         break;
  49.                 case PR_MOBILE_TELEPHONE_NUMBER_W:
  50.                         wcscpy (numbers[iPhoneCnt].szPhoneType, L"m");
  51.                         break;
  52.                 case PR_RADIO_TELEPHONE_NUMBER_W:
  53.                         wcscpy (numbers[iPhoneCnt].szPhoneType, L"radio");
  54.                         break;
  55.                 case PR_PRIMARY_TELEPHONE_NUMBER_W:
  56.                         wcscpy (numbers[iPhoneCnt].szPhoneType, L"prim.");
  57.                         break;
  58.                 default:
  59.                         continue;
  60.                 }

  61.                 if (wcslen (ppv->val.lpwstr) >= MAX_PHONE)
  62.                         continue;

  63.                 wcscpy (numbers[iPhoneCnt].szPhone, ppv->val.lpwstr);
  64.                 ++iPhoneCnt;
  65.         }

  66.         if (iPhoneCnt < PHONE_NUM) {
  67.                 numbers[iPhoneCnt].szPhone[0] = '\0';
  68.                 numbers[iPhoneCnt].szPhoneType[0] = '\0';
  69.         }

  70.         int ndx = DialogBoxParam (ghInst, MAKEINTRESOURCE (IDD_DIALOG1), NULL, WhichDlg, (LPARAM)numbers);

  71.         if ((ndx >= 0) && (ndx < iPhoneCnt)) {
  72.                 PROCESS_INFORMATION pi;
  73.                 STARTUPINFO                si;

  74.                 memset (&pi, 0, sizeof(pi));
  75.                 memset (&si, 0, sizeof(si));
  76.                 si.cb = sizeof(si);

  77.                 DWORD bCP = CreateProcess (L"btdialer.exe", numbers[ndx].szPhone, NULL, NULL, FALSE, 0, NULL,
  78.                                         NULL, &si, &pi);

  79.                 if (bCP) {
  80.                         CloseHandle (pi.hThread);
  81.                         CloseHandle (pi.hProcess);
  82.                 }
  83.         }

  84.         return;
  85. }
复制代码
 
 
 

回复
您需要登录后才可以回帖 登录 | 注册

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/10 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表