memory leak

Started by Michael P. Soulierabout 14 years ago3 messagesgeneral
Jump to latest
#1Michael P. Soulier
michael_soulier@mitel.com

Hi,

I've written a small multi-threaded C program using libpq, and valgrind is
reporting a memory leak.

2012-01-10 13:45:07.263078500 ==12695== 608 bytes in 4 blocks are definitely lost in loss record 19 of 22
2012-01-10 13:45:07.263097500 ==12695== at 0x4005B83: malloc (vg_replace_malloc.c:195)
2012-01-10 13:45:07.263116500 ==12695== by 0x34AD94: PQmakeEmptyPGresult (in /usr/lib/libpq.so.5.2)
2012-01-10 13:45:07.263133500 ==12695== by 0x35466F: ??? (in /usr/lib/libpq.so.5.2)
2012-01-10 13:45:07.263149500 ==12695== by 0x349E83: ??? (in /usr/lib/libpq.so.5.2)
2012-01-10 13:45:07.263167500 ==12695== by 0x34B008: PQgetResult (in /usr/lib/libpq.so.5.2)
2012-01-10 13:45:07.263184500 ==12695== by 0x34B26B: ??? (in /usr/lib/libpq.so.5.2)
2012-01-10 13:45:07.263201500 ==12695== by 0x8048E1C: ??? (in /usr/sbin/tug-queue-counter)
2012-01-10 13:45:07.263218500 ==12695== by 0x8049029: ??? (in /usr/sbin/tug-queue-counter)
2012-01-10 13:45:07.263236500 ==12695== by 0xC05831: start_thread (in /lib/libpthread-2.5.so)
2012-01-10 13:45:07.263254500 ==12695== by 0xB3046D: clone (in /lib/libc-2.5.so)

Now, I'm trying to figure out what I'm doing wrong. I'm working from example
code found on the postgres site...

This thread wakes up periodically to update a db value like so...

void
update_queue_size(int size)
{
// Critical section around event_count
pthread_mutex_lock(&counter_mutex);
printf("DB: Setting event_queue_size to %ld\n", event_count);
sprintf(commandbuf, command_format, event_count);
printf("DB: Command is: %s\n", commandbuf);

res = PQexec(conn, "BEGIN");
if (PQresultStatus(res) != PGRES_COMMAND_OK)
{
fprintf(stderr, "DB: BEGIN command failed: %s", PQerrorMessage(conn));
PQclear(res);
exit_nicely(conn);
}

res = PQexec(conn, commandbuf);
if (PQresultStatus(res) != PGRES_COMMAND_OK)
{
fprintf(stderr, "DB: UPDATE command failed: %s", PQerrorMessage(conn));
PQclear(res);
exit_nicely(conn);
}

/* end the transaction */
res = PQexec(conn, "END");
PQclear(res);
// end critical section
pthread_mutex_unlock(&counter_mutex);
}

where exit_nicely() is

void
exit_nicely(PGconn *conn)
{
PQfinish(conn);
exit(1);
}

Can anyone point out improper use of libpq here?

Thanks,
mps

#2Simon Riggs
simon@2ndQuadrant.com
In reply to: Michael P. Soulier (#1)
Re: memory leak

On Tue, Jan 10, 2012 at 6:48 PM, Michael P. Soulier
<michael_soulier@mitel.com> wrote:

   res = PQexec(conn, "BEGIN");
   if (PQresultStatus(res) != PGRES_COMMAND_OK)
   {
       fprintf(stderr, "DB: BEGIN command failed: %s", PQerrorMessage(conn));
       PQclear(res);
       exit_nicely(conn);
   }

   res = PQexec(conn, commandbuf);
   if (PQresultStatus(res) != PGRES_COMMAND_OK)
   {
       fprintf(stderr, "DB: UPDATE command failed: %s", PQerrorMessage(conn));
       PQclear(res);
       exit_nicely(conn);
   }

   /* end the transaction */
   res = PQexec(conn, "END");
   PQclear(res);

You're missing 2 PQclear() calls on success.

http://www.postgresql.org/docs/devel/static/libpq-exec.html#LIBPQ-EXEC-MAIN

PQclear

Frees the storage associated with a PGresult. Every command result
should be freed via PQclear when it is no longer needed.

void PQclear(PGresult *res);

You can keep a PGresult object around for as long as you need it;
it does not go away when you issue a new command, nor even if you
close the connection. To get rid of it, you must call PQclear. Failure
to do this will result in memory leaks in your application.

--
 Simon Riggs                   http://www.2ndQuadrant.com/
 PostgreSQL Development, 24x7 Support, Training & Services

#3Michael P. Soulier
michael_soulier@mitel.com
In reply to: Simon Riggs (#2)
Re: memory leak

On 10/01/12 Simon Riggs said:

You're missing 2 PQclear() calls on success.

http://www.postgresql.org/docs/devel/static/libpq-exec.html#LIBPQ-EXEC-MAIN

Ah, thanks.

Diffing db.c to db.c@@/main/soulierm_MASTeleworker_dev1/3
--- db.c@@/main/soulierm_MASTeleworker_dev1/3   2011-08-10 07:09:27.000000000
-0
400
+++ db.c        2012-01-10 14:15:21.070872000 -0500
@@ -39,6 +39,7 @@
         PQclear(res);
         exit_nicely(conn);
     }
+    PQclear(res);

res = PQexec(conn, commandbuf);
if (PQresultStatus(res) != PGRES_COMMAND_OK)
@@ -47,6 +48,7 @@
PQclear(res);
exit_nicely(conn);
}
+ PQclear(res);

/* end the transaction */
res = PQexec(conn, "END");

mps