hello,

this segfault is all about PQclear();

according to the docs libpq-exec.html

#

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

void PQclear(PQresult *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 query, 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 the frontend application.

#

I've been playing with the pg example, writing some functions for later 
inclusion into a project i'm working on when all of a sudden my 
(incredibly simple) program started to segfault. I checked my code, I 
let other people check my code, I asked on irc... so far, I can't find 
bug on my side, so I suppose it's a bug inside PQclear();
This only happened to me when the PQresult *res was just made and hadn't 
been used before. The example code should give more clarity (please 
compile as given). Note that using something as

res = PQmakeEmptyPGresult(conn, status);
PQclear(res); 


first prevents the program from segfaulting, however, it should have not 
  segfaulted in the first place.

version used to compile and run are below.
postgres:
(PostgreSQL) 7.2.1
glibc:
GNU C Library stable release version 2.2.4 Compiled by GNU CC           version 
2.95.3 20010315 (release).Compiled on a Linux 2.4.14 system on 2001-11-09.
gcc:
gcc 2.95.3
kernel:
Linux pathfinder 2.4.18 #1 SMP Fri Mar 22 17:10:20 CET 2002 i686 unknown
build script used to compile this program:
rm pqtest
gcc -g -Wall -I /opt/postgresql/include -L /opt/postgresql/lib -lpgeasy 
-lpq pqtest.c -o pqtest


I hope you can determine what is going wrong, please keep me informed 
should you be able to find the cause of this.


Kind regards,

Eric van Lent


note: I also included the code as attachment



*/ CODE START */
#include <stdio.h>
#include <stdlib.h>
#include "libpq-fe.h"
#include <string.h>

int DBinsertCmd(char *, char *, PGconn *, PGresult *);
int DBcontrol();

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

int  main()
{
        int i = 30;
        int n = 0;
        char *pghost, *pgport, *pgoptions, *pgtty, *dbName, *login, *pwd, *result;
        char *tablename = "files";
        char *valueOne = "BlahCompatible";
        
        PGconn *conn;
        PGresult *res;
        ExecStatusType status;
                        
        pghost = NULL;                          /* host name of the backend server */
        pgport = NULL;                          /* port of the backend server */
        pgoptions = NULL;                       /* special options to start up the 
backend server */
        pgtty = NULL;                           /* debugging tty for the backend 
server */
        dbName = "void";                        /* change this to the name of your 
test * database */
        login = "void";
        pwd = NULL;                             /* no pwd for now */
        
        conn = PQsetdbLogin(pghost, pgport, pgoptions, pgtty, dbName, login, 
pwd); /* make a connection to the database */
        
        if (PQstatus(conn) == CONNECTION_BAD){ /* check to see that the backend 
connection was successfully made */
                fprintf(stderr, "Connection to database '%s' failed.\n", dbName);
                fprintf(stderr, "%s", PQerrorMessage(conn));
                exit_nicely(conn);
        }
        
        //res = PQmakeEmptyPGresult(conn, status);
        //PQclear(res); 
        
        if ((DBinsertCmd(tablename, valueOne, conn, res)) == -1)
                fprintf(stderr,"DBinsertCmd exited with -1\n");
        PQclear(res);

        res = PQexec(conn, "SELECT * FROM files");
        while (PQresultStatus(res) == PGRES_TUPLES_OK && n < i){
                result = PQgetvalue(res, n, 0);
                n++;
                fprintf(stdout,"resultaat: %s\n",result);
        }
        PQclear(res);   /* PQclear(res) should PQclear PGresult whenever it is no 
longer needed to avoid memory leaks */
        
        PQfinish(conn); /* close the connection to the database and cleanup */
        return 0;               /* Though PQfinish(conn1) has called exit(1) */
}

int DBinsertCmd(char *tablename, char *valueOne, PGconn *conn, PGresult 
*res)
{
        char finalCmd[512];
        
        if ((snprintf(finalCmd, 511, "INSERT INTO %s VALUES ('%s')", tablename, 
valueOne)) == -1){
                fprintf(stderr,"DBinsertCmd: WARNING! string \"%s\" was longer then 
allowed, this should not have happened",finalCmd);
                return -1;
        }
        fprintf(stdout,"%s\n",finalCmd);
        
        res = PQexec(conn, finalCmd);
        if (PQresultStatus(res) != PGRES_COMMAND_OK){
                fprintf(stderr, "INSERT command failed: error returned by DB is: 
%s\n",PQresStatus(PQresultStatus(res)));
                return -1;
        }
        return 1;
}



/* CODE END */
#include <stdio.h>
#include <stdlib.h>
#include "libpq-fe.h"
#include <string.h>

int DBinsertCmd(char *, char *, PGconn *, PGresult *);
int DBcontrol();

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

int  main()
{
        int i = 30;
        int n = 0;
        char *pghost, *pgport, *pgoptions, *pgtty, *dbName, *login, *pwd, *result;
        char *tablename = "files";
        char *valueOne = "BlahCompatible";
        
        PGconn *conn;
        PGresult *res;
        ExecStatusType status;
                        
        pghost = NULL;                          /* host name of the backend server */
        pgport = NULL;                          /* port of the backend server */
        pgoptions = NULL;                       /* special options to start up the 
backend server */
        pgtty = NULL;                           /* debugging tty for the backend 
server */
        dbName = "void";                        /* change this to the name of your 
test * database */
        login = "void";
        pwd = NULL;                             /* no pwd for now */
        
        conn = PQsetdbLogin(pghost, pgport, pgoptions, pgtty, dbName, login, pwd); /* 
make a connection to the database */
        
        if (PQstatus(conn) == CONNECTION_BAD){ /* check to see that the backend 
connection was successfully made */
                fprintf(stderr, "Connection to database '%s' failed.\n", dbName);
                fprintf(stderr, "%s", PQerrorMessage(conn));
                exit_nicely(conn);
        }
        
        res = PQmakeEmptyPGresult(conn, status);
        //PQclear(res); 
        
        if ((DBinsertCmd(tablename, valueOne, conn, res)) == -1)
                fprintf(stderr,"DBinsertCmd exited with -1\n");
        PQclear(res);

        res = PQexec(conn, "SELECT * FROM files");
        while (PQresultStatus(res) == PGRES_TUPLES_OK && n < i){
                result = PQgetvalue(res, n, 0);
                n++;
                fprintf(stdout,"resultaat: %s\n",result);
        }
        PQclear(res);   /* PQclear(res) should PQclear PGresult whenever it is no 
longer needed to avoid memory leaks */
        
        PQfinish(conn); /* close the connection to the database and cleanup */
        return 0;               /* Though PQfinish(conn1) has called exit(1) */
}

int DBinsertCmd(char *tablename, char *valueOne, PGconn *conn, PGresult *res)
{
        char finalCmd[512];
        
        if ((snprintf(finalCmd, 511, "INSERT INTO %s VALUES ('%s')", tablename, 
valueOne)) == -1){
                fprintf(stderr,"DBinsertCmd: WARNING! string \"%s\" was longer then 
allowed, this should not have happened",finalCmd);
                return -1;
        }
        fprintf(stdout,"%s\n",finalCmd);
        
        res = PQexec(conn, finalCmd);
        if (PQresultStatus(res) != PGRES_COMMAND_OK){
                fprintf(stderr, "INSERT command failed: error returned by DB is: 
%s\n",PQresStatus(PQresultStatus(res)));
                return -1;
        }
        return 1;
}

---------------------------(end of broadcast)---------------------------
TIP 3: if posting/reading through Usenet, please send an appropriate
subscribe-nomail command to [EMAIL PROTECTED] so that your
message can get through to the mailing list cleanly

Reply via email to