valgrind为何 报 ecpg内存泄露错误?根据我的同事的研究成果:
究其原因,全局变量 sqlca 由malloc形成,但是释放时是隐含的:
ecpg_sqlca_key_destructor函数调用 free 进行释放。
复制代码
bool
ECPGconnect(int lineno, int c, const char *name, const char *user, const char *passwd, const char *connection_name, int autocommit){
struct sqlca_t *sqlca = ECPGget_sqlca();
......
struct sqlca_t *
ECPGget_sqlca(void)
{
#ifdef ENABLE_THREAD_SAFETY
struct sqlca_t *sqlca;
pthread_once(&sqlca_key_once, ecpg_sqlca_key_init);
sqlca = pthread_getspecific(sqlca_key);
if (sqlca == NULL){
sqlca = malloc(sizeof(struct sqlca_t));
ecpg_init_sqlca(sqlca);
pthread_setspecific(sqlca_key, sqlca);
}
return (sqlca);
#else
return (&sqlca);
#endif
}
static void
ecpg_sqlca_key_init(void){
pthread_key_create(&sqlca_key, ecpg_sqlca_key_destructor);
}
static void
ecpg_sqlca_key_destructor(void *arg){
free(arg); /* sqlca structure allocated in ECPGget_sqlca */
}
复制代码
用GDB来调试,也可以验证这一点:
复制代码
GNU gdb (GDB) Red Hat Enterprise Linux (7.2-50.el6)
Copyright (C) 2010 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "i686-redhat-linux-gnu".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
(gdb) file memoryleak
Reading symbols from /usr/local/pgsql/bin/memoryleak...done.
(gdb) break main
Breakpoint 1 at 0x804875e: file memoryleak.pgc, line 51.
(gdb) run
Starting program: /usr/local/pgsql/bin/memoryleak
[Thread debugging using libthread_db enabled]
Breakpoint 1, main (argc=1, argv=0xbffff6f4) at memoryleak.pgc:51
51 PerformTask( 25 );
Missing separate debuginfos, use: debuginfo-install glibc-2.12-1.80.el6.i686
(gdb) delete
Delete all breakpoints? (y or n) y
(gdb) break ecpg_sqlca_key_destructor
Breakpoint 2 at 0x1af9b2: file misc.c, line 124.
(gdb) list misc.c:124
119
120 #ifdef ENABLE_THREAD_SAFETY
121 static void
122 ecpg_sqlca_key_destructor(void *arg)
123 {
124 free(arg); /* sqlca structure allocated in ECPGget_sqlca */
125 }
126
127 static void
128 ecpg_sqlca_key_init(void)
(gdb) break misc.c:147
Breakpoint 3 at 0x1afa4e: file misc.c, line 147.
(gdb) list misc.c:134,misc.c:149
134 struct sqlca_t *
135 ECPGget_sqlca(void)
136 {
137 #ifdef ENABLE_THREAD_SAFETY
138 struct sqlca_t *sqlca;
139
140 pthread_once(&sqlca_key_once, ecpg_sqlca_key_init);
141
142 sqlca = pthread_getspecific(sqlca_key);
143 if (sqlca == NULL)
144 {
145 sqlca = malloc(sizeof(struct sqlca_t));
146 ecpg_init_sqlca(sqlca);
147 pthread_setspecific(sqlca_key, sqlca);
148 }
149 return (sqlca);
(gdb) cont
Continuing.
[New Thread 0xb7ff0b70 (LWP 2936)]
[Switching to Thread 0xb7ff0b70 (LWP 2936)]
Breakpoint 3, ECPGget_sqlca () at misc.c:147
147 pthread_setspecific(sqlca_key, sqlca);
(gdb) where
#0 ECPGget_sqlca () at misc.c:147
#1 0x001aed62 in ECPGconnect (lineno=29, c=0, name=0xb7400468 "postgres@192.168.66.123:5432", user=0x804884b "postgres", passwd=0x804884b "postgres",
connection_name=0x8048844 "dbConn", autocommit=0) at connect.c:268
#2 0x080486bf in Work () at memoryleak.pgc:29
#3 0x00117a49 in start_thread () from /lib/libpthread.so.0
#4 0x00353e1e in clone () from /lib/libc.so.6
(gdb) print sqlca
$1 = (struct sqlca_t *) 0xb7400490
(gdb) cont
Continuing.
conncet ok
Breakpoint 2, ecpg_sqlca_key_destructor (arg=0xb7400490) at misc.c:124
124 free(arg); /* sqlca structure allocated in ECPGget_sqlca */
Missing separate debuginfos, use: debuginfo-install libgcc-4.4.6-4.el6.i686
(gdb) print arg
$2 = (void *) 0xb7400490
(gdb) cont
Continuing.
[Thread 0xb7ff0b70 (LWP 2936) exited]
Program exited normally.
(gdb)
复制代码
我的追记:后来经过确认,这还不是全部,GDB运行时加了开关才会如此。
需要加入 pthread_exit(NULL)线程终止退出函数,才会触发。目前,仍然被认为是有内存泄漏的。
下面会记录我用普通方法得到的结论。
本文转自健哥的数据花园博客园博客,原文链接:http://www.cnblogs.com/gaojian/archive/2012/08/14/2637933.html,如需转载请自行联系原作者