• 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识别得不好。我们下回接着研究。

  • 相关阅读:
    python 类的自定义属性
    好的設計模式
    sql server 过滤重复数据
    sql server 2000 sp3
    css
    SQL server 与Oracle开发比较(同事帮忙整理的,放这里方便查询)
    深圳 帮部门招聘人才
    BCP等三個sql server 過程
    CTE and CONNECT BY 樹的查詢(轉)
    继承System.Web.UI.Page的页面基类
  • 原文地址:https://www.cnblogs.com/gaojian/p/2637891.html
Copyright © 2020-2023  润新知