valgrind 报告 ecpg内存泄露

简介:
客户说 valgrind 报告 ecpg内存泄露,实际到底如何呢?

用程序来进行验证:我的test.pc 程序:

复制代码
#include <stdio.h>                                        
#include <string.h>                                        
#include <stdlib.h>                                        
int tst_connectdb(const char *Uid,const char *Pswd,const char *Host,char *SqlErrm){                                        
  EXEC SQL BEGIN DECLARE SECTION;                                        
        varchar  sUserid[10];                                        
        varchar  sPasswd[10];                                        
        varchar  sHostname[10];                                        
  EXEC SQL END DECLARE SECTION;         
  memset(sUserid.arr, '\0',sizeof(sUserid.arr)); 
  memset(sPasswd.arr, '\0',sizeof(sPasswd.arr));  
  memset(sHostname.arr, '\0',sizeof(sHostname.arr)); 
  if (Uid == NULL || Pswd == NULL ||                                         
           Host == NULL || SqlErrm == NULL){   
       return -1;                                        
  }                                    
  strcpy((char *)sUserid.arr, Uid);                                        
  sUserid.len = (unsigned short)strlen((char *)sUserid.arr); 
  strcpy((char *)sPasswd.arr, pcDbPswd);                                        
  sPasswd.len = (unsigned short)strlen((char *)sPasswd.arr); 
  strcpy((char *)sHostname.arr, pcHostname);                                        
  sHostname.len = (unsigned short)strlen((char *)sHostname.arr);
  EXEC SQL CONNECT TO:sHostname AS TST_DBCONN USER:sUserid IDENTIFIED BY:sPasswd;
  if (sqlca.sqlcode!=0){                                        
    return -1;                                        
  }                                        
  return 0;                                        
}                                        
                                        
int main(){                                        
  int ist=0;                                        
  char * perr;                                        
  perr = (char *) malloc (sizeof(char)*64);  
  const char * pusr="testusr";                                        
  const char * ppass="testpass";                                        
  const char * phost="testhost";       
  ist= tst_connectdb(pusr,ppass,phost,perr);  
  free(perr);                                        
  return 0;                                        
}                                        
复制代码
而预编译而成的程序如下 test.c:

复制代码
/* Processed by ecpg (4.7.0) */                                        
/* These include files are added by the preprocessor */
#include <ecpglib.h>                                        
#include <ecpgerrno.h>                                        
#include <sqlca.h>                                        
/* End of automatic include section */                                        
                                        
#line 1 "test.pc"                                        
#include <stdio.h>                                        
#include <string.h>                                        
#include <stdlib.h>                                        
int  tst_connectdb(const char *Uid,const char *pcDbPswd,const char *pcHostname,char *pcSqlErrm){                                        
/* exec sql begin declare section */ 
#line 7 "test.pc"                                        
  struct varchar_sUserid_1  { int len; char arr[ 10 ]; }  sUserid ; 
#line 8 "test.pc"                                        
  struct varchar_sPasswd_2  { int len; char arr[ 10 ]; }  sPasswd ; 
#line 9 "test.pc"                                        
  struct varchar_sHostname_3  { int len; char arr[ 10 ]; }  sHostname ;
/* exec sql end declare section */                                        
#line 10 "test.pc"                    
  memset(sUserid.arr, '\0',sizeof(sUserid.arr));
  memset(sPasswd.arr, '\0',sizeof(sPasswd.arr)); 
  memset(sHostname.arr, '\0',sizeof(sHostname.arr)); 
  if (Uid == NULL || pcDbPswd == NULL ||                                         
           pcHostname == NULL || pcSqlErrm == NULL){
       return -1;                                        
  }                                         
  strcpy((char *)sUserid.arr, Uid);                                        
  sUserid.len = (unsigned short)strlen((char *)sUserid.arr); 
  strcpy((char *)sPasswd.arr, pcDbPswd);                                        
  sPasswd.len = (unsigned short)strlen((char *)sPasswd.arr);
  strcpy((char *)sHostname.arr, pcHostname); 
  sHostname.len = (unsigned short)strlen((char *)sHostname.arr); 
  { ECPGconnect(__LINE__, 0, sHostname.arr , sUserid.arr , sPasswd.arr , "TST_DBCONN", 0); }                                        
#line 29 "test.pc"                    
  if (sqlca.sqlcode!=0){                                        
    return -1;                                        
  }                                        
  return 0;                                        
}                                        
                                        
int main(){                                        
  int ist=0;                                        
  char * perr;                                        
  perr = (char *) malloc (sizeof(char)*64);
  const char * pusr="testusr";                                        
  const char * ppass="testpass";                                        
  const char * phost="testhost";      
  ist=  tst_connectdb(pusr,ppass,phost,perr); 
  free(perr);                                        
  return 0;                                        
}
复制代码
对test.c进行编译后,用valgrind进行检验:

valgrind ./test.o

复制代码
[root@post1 gao]# /usr/local/pgsql/bin/ecpg -o test.c test.pc 
[root@post1 gao]# gcc -o test.o test.c -I /usr/local/pgsql/include -L/usr/local/pgsql/lib -lecpg                                    
[root@post1 gao]# valgrind ./test.o                                    
==4965== Memcheck, a memory error detector                                    
==4965== Copyright (C) 2002-2012, and GNU GPL'd, by Julian Seward et al. 
==4965== Using Valgrind-3.8.0 and LibVEX; rerun with -h for copyright info 
==4965== Command: ./test.o                                    
==4965==                                     
==4965== Invalid free() / delete / delete[] / realloc()  
==4965==    at 0x4006A9D: free (vg_replace_malloc.c:446) 
==4965==    by 0xB0321D: free_mem (in /lib/libc-2.5.so) 
==4965==    by 0xB02D96: __libc_freeres (in /lib/libc-2.5.so) 
==4965==    by 0x4001468: _vgnU_freeres (vg_preloaded.c:62)
==4965==    by 0xA83013: _Exit (in /lib/libc-2.5.so)
==4965==    by 0xA06EA3: (below main) (in /lib/libc-2.5.so) 
==4965==  Address 0x4000b78 is not stack'd, malloc'd or (recently) free'd 
==4965==                                     
==4965==                                     
==4965== HEAP SUMMARY:                                    
==4965==     in use at exit: 220 bytes in 1 blocks 
==4965==   total heap usage: 31 allocs, 31 frees, 35,279 bytes allocated 
==4965==                                     
==4965== LEAK SUMMARY:                                    
==4965==    definitely lost: 0 bytes in 0 blocks 
==4965==    indirectly lost: 0 bytes in 0 blocks 
==4965==      possibly lost: 0 bytes in 0 blocks 
==4965==    still reachable: 220 bytes in 1 blocks 
==4965==         suppressed: 0 bytes in 0 blocks
==4965== Rerun with --leak-check=full to see details of leaked memory 
==4965==                                     
==4965== For counts of detected and suppressed errors, rerun with: -v
==4965== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 21 from 8)
[root@post1 gao]#                                     
复制代码
对于 invalid free()那一段,可以忽略不计。这是因为,即使是 int main(){},也会这么报错。

最关键的就是:still reachable: 220 bytes in 1 blocks

为了研究其原因,把如下这一段代码注释掉:

  /**                                        
  EXEC SQL CONNECT TO :sHost AS TST_DBCONN USER:sUserid IDENTIFIED BY :sPasswd;
  if (sqlca.sqlcode!=0){                                        
    return -1;                                        
  }                                        
 */                    
再看 valgrind ./test.o 就不再出现 still reachable 信息了:

==4990== HEAP SUMMARY:                                    
==4990==     in use at exit: 0 bytes in 0 blocks 
==4990==   total heap usage: 1 allocs, 2 frees, 64 bytes allocated 
==4990==                                     
==4990== All heap blocks were freed -- no leaks are possible 
所以,EXEC SQL CONNECT 会导致 valgrind 判断它有未释放的内存。

那么是否真的如此呢,其实并不是泄露,而是valgrind 对 ecpg识别得不好。我们下回接着研究。


本文转自健哥的数据花园博客园博客,原文链接:http://www.cnblogs.com/gaojian/archive/2012/08/14/2637891.html,如需转载请自行联系原作者
目录
相关文章
|
8月前
|
人工智能 监控 机器人
【Valgrind】如何使用Valgrind监控内存
【Valgrind】如何使用Valgrind监控内存
|
存储 XML NoSQL
提高代码质量,避免内存泄漏:深入探索Valgrind工具
提高代码质量,避免内存泄漏:深入探索Valgrind工具
|
8月前
|
IDE Linux 开发工具
内存泄漏检测工具Valgrind:C++代码问题检测的利器(一)
内存泄漏检测工具Valgrind:C++代码问题检测的利器
1722 0
|
8月前
|
缓存 测试技术 开发工具
内存泄漏检测工具Valgrind:C++代码问题检测的利器(二)
内存泄漏检测工具Valgrind:C++代码问题检测的利器
210 0
|
8月前
|
XML NoSQL Linux
内存泄漏专题(3)内存泄漏调试神器valgrind
内存泄漏专题(3)内存泄漏调试神器valgrind
126 0
|
8月前
|
XML 存储 NoSQL
内存泄漏检测工具valgrind神器
内存泄漏检测工具valgrind神器
149 0
|
XML 存储 缓存
内存泄漏检测神器valgrind
Valgrind是一款用于内存调试、内存泄漏检测以及性能分析的软件开发工具。
695 0
|
Linux C++ 分布式计算
C/C++的内存泄漏检测工具Valgrind memcheck的使用经历
Linux下的Valgrind真是利器啊(不知道Valgrind的请自觉查看参考文献(1)(2)),帮我找出了不少C++中的内存管理错误,前一阵子还在纠结为什么VS 2013下运行良好的程序到了Linux下用g++编译运行却崩溃了,给出一堆汇编代码也看不懂。
1507 0
基于WinDbg的内存泄漏分析
在前面C++中基于Crt的内存泄漏检测一文中提到的方法已经可以解决我们的大部分内存泄露问题了,但是该方法是有前提的,那就是一定要有源代码,而且还只能是Debug版本调试模式下。实际上很多时候我们的程序会用到第三方没有源代码的模块,有些情况下我们甚至怀疑系统模块有内存泄露,但是有没有证据,我们该怎么办? 这时我们就要依靠无所不能的WinDbg了。
1170 0
使用valgrind检查内存问题
作者:gfree.wind@gmail.com 博客:blog.focus-linux.net   linuxfocus.blog.chinaunix.net    本文的copyleft归gfree.wind@gmail.com所有,使用GPL发布,可以自由拷贝,转载。
992 0