[C] [PostgreSQL] PqExec et Segmentation Fault

Fermé
SangJun - 31 mai 2007 à 15:45
 Pierrot le developpeur fou - 19 mai 2009 à 10:33
Bonjour,

Comment se fait que PgExec génère une erreur de segmentation pour une requête qui s'exécute "manuellement" si on la copie-colle sur PgAdmin?

J'ai beau retourner le problème dans tout les sens, je ne vois pas comment m'en sortir. Je copie-colle le code pour donner un peu plus de détails.

Merci de votre aide


[CODE]#include <stdio.h>
#include <stdlib.h>
#include "libpq-fe.h"

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

int bande()
{
const char *conninfo;
PGconn *conn;
PGresult *res;
int nFields;
int i, j;

char maRequete[250];

int i = 1; int j = 2;

conninfo = "***chaine pour se connecter***";

/* Make a connection to the database */
conn = PQconnectdb(conninfo);

/* Check to see that the backend connection was successfully made */
if (PQstatus(conn) != CONNECTION_OK)
{
fprintf(stderr, "Connection to database failed: %s", PQerrorMessage(conn));
exit_nicely(conn);
}

/* Start a transaction block */
res = PQexec(conn, "BEGIN");
if (PQresultStatus(res) != PGRES_COMMAND_OK)
{
fprintf(stderr, "BEGIN command failed: %s", PQerrorMessage(conn));
PQclear(res);
exit_nicely(conn);
}

/*
* Should PQclear PGresult whenever it is no longer needed to avoid memory
* leaks
*/
PQclear(res);


while(j<=nbPoints)
{ strcpy(maRequete,"***une requete***");

printf("%s \n",maRequete);

res = PQexec(conn,maRequete);

if (PQresultStatus(res) != PGRES_TUPLES_OK)
{
fprintf(stderr, "SELECT failed: %s \n", PQerrorMessage(conn));
fprintf(stderr, "maRequete= %s \n", maRequete);
PQclear(res);
exit_nicely(conn);
}

PQclear(res);

if (i==1) //Si c'est le premier segment, on crée le premier polygone
{
strcpy(maRequete,"***une requete***");

res = PQexec(conn,maRequete);

if (PQresultStatus(res) != PGRES_TUPLES_OK)
{
fprintf(stderr, "SELECT failed: %s \n", PQerrorMessage(conn));
fprintf(stderr, "maRequete= %s \n", maRequete);
PQclear(res);
exit_nicely(conn);
}

PQclear(res);
}else // Sinon on fait une union avec le nouveau polygone
{
strcpy(maRequete,"***une requete***");

printf("%s\n",maRequete);

res = PQexec(conn,maRequete); /* Instruction qui génère l'erreur de segmentation */

if (PQresultStatus(res) != PGRES_TUPLES_OK)
{
fprintf(stderr, "SELECT failed: %s \n", PQerrorMessage(conn));
fprintf(stderr, "maRequete= %s \n", maRequete);
PQclear(res);
exit_nicely(conn);
}

PQclear(res);
}

i++;
j++;
}

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

/* close the connection to the database and cleanup */
PQfinish(conn);

return 0;
}[/CODE]

18 réponses

Pierrot le developpeur fou
19 mai 2009 à 10:33
J'ai eu le meme probleme qui m'a fait perdre du temps.

En fait, c'etait la taille alloué pour ma requete qui était trop faible.

char maRequete[250];

Si ta requete est une chaine de caractere de plus de 250 lettres. Ton PQExec générera une erreur de segmentation

Met char maRequete[400]; ou plus et ca marchera
1
kilian Messages postés 8731 Date d'inscription vendredi 19 septembre 2003 Statut Modérateur Dernière intervention 20 août 2016 1 527
31 mai 2007 à 16:11
Salut,

Tu es sous Linux?
Je te suggère t'enquêter un ptit coup pour connaître la ligne "coupable":
langage c c c erreur de segmentation
0
SangJun_ Messages postés 17 Date d'inscription jeudi 31 mai 2007 Statut Membre Dernière intervention 28 septembre 2011
31 mai 2007 à 16:29
Je me retrouve avec :

(gdb) run
Starting program: /dea/fsauvage/nouveau
[Thread debugging using libthread_db enabled]
[New Thread -1212294464 (LWP 18936)]

Program received signal SIGSEGV, Segmentation fault.
[Switching to Thread -1212294464 (LWP 18936)]
0xb7fca5c9 in PQconsumeInput () from /usr/lib/libpq.so.4
(gdb) bt
#0  0xb7fca5c9 in PQconsumeInput () from /usr/lib/libpq.so.4
#1  0xb7fcaf07 in PQgetResult () from /usr/lib/libpq.so.4
#2  0xb7fcb2c5 in PQputCopyEnd () from /usr/lib/libpq.so.4
#3  0xb7fcb50f in PQexec () from /usr/lib/libpq.so.4
#4  0x080495fe in bande () at bande.c:254
#5  0x08049841 in main () at bande.c:315


:-/
0
kilian Messages postés 8731 Date d'inscription vendredi 19 septembre 2003 Statut Modérateur Dernière intervention 20 août 2016 1 527
31 mai 2007 à 16:55
C'est donc ça l'important:
#4  0x080495fe in bande () at bande.c:254

C'est à dire l'appel de fonction ou méthode le plus profond sans entrer dans une librairie externe.

Ton problème se situe dans la fonction bande à la ligne 254 de bande.c

Regarde si par là tu utilises un pointeur non initialisé ou un truc du style...

Ca correspond à quelle ligne en fait?
0
SangJun_ Messages postés 17 Date d'inscription jeudi 31 mai 2007 Statut Membre Dernière intervention 28 septembre 2011
31 mai 2007 à 17:01
Il s'agit justement de la ligne
res = PQexec(conn,maRequete); /* Instruction qui génère l'erreur de segmentation */ 


NOTE : j'initialise maintenant conninfo avec un strdup
0
kilian Messages postés 8731 Date d'inscription vendredi 19 septembre 2003 Statut Modérateur Dernière intervention 20 août 2016 1 527
31 mai 2007 à 17:06
Ah d'accord, tu connaissais déjà la ligne...
De fait, j'avais pas trop lu ton code car l'indentation n'apparait pas si tu n'utilises pas les balises de code

Peux-tu le réafficher avec ces balises?
Sinon, je pourrai pas y comprendre grand chose....
0
SangJun_ Messages postés 17 Date d'inscription jeudi 31 mai 2007 Statut Membre Dernière intervention 28 septembre 2011
1 juin 2007 à 09:55
Voilà qui sera plus clair

#include <stdio.h>
#include <stdlib.h>
#include "libpq-fe.h"

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

int bande()
{
const char *conninfo;
PGconn *conn;
PGresult *res;
int nFields;
int i, j;

char maRequete[250];

int i = 1; int j = 2;

conninfo = "***chaine pour se connecter***";

/* Make a connection to the database */
conn = PQconnectdb(conninfo);

/* Check to see that the backend connection was successfully made */
if (PQstatus(conn) != CONNECTION_OK)
{
fprintf(stderr, "Connection to database failed: %s", PQerrorMessage(conn));
exit_nicely(conn);
}

/* Start a transaction block */
res = PQexec(conn, "BEGIN");
if (PQresultStatus(res) != PGRES_COMMAND_OK)
{
fprintf(stderr, "BEGIN command failed: %s", PQerrorMessage(conn));
PQclear(res);
exit_nicely(conn);
}

/*
* Should PQclear PGresult whenever it is no longer needed to avoid memory
* leaks
*/
PQclear(res);


while(j<=nbPoints)
{ strcpy(maRequete,"***une requete***");

printf("%s \n",maRequete);

res = PQexec(conn,maRequete);

if (PQresultStatus(res) != PGRES_TUPLES_OK)
{
fprintf(stderr, "SELECT failed: %s \n", PQerrorMessage(conn));
fprintf(stderr, "maRequete= %s \n", maRequete);
PQclear(res);
exit_nicely(conn);
}

PQclear(res);

if (i==1) //Si c'est le premier segment, on crée le premier polygone
{
strcpy(maRequete,"***une requete***");

res = PQexec(conn,maRequete);

if (PQresultStatus(res) != PGRES_TUPLES_OK)
{
fprintf(stderr, "SELECT failed: %s \n", PQerrorMessage(conn));
fprintf(stderr, "maRequete= %s \n", maRequete);
PQclear(res);
exit_nicely(conn);
}

PQclear(res);
}else // Sinon on fait une union avec le nouveau polygone
{
strcpy(maRequete,"***une requete***");

printf("%s\n",maRequete);

res = PQexec(conn,maRequete); /* Instruction qui génère l'erreur de segmentation */

if (PQresultStatus(res) != PGRES_TUPLES_OK)
{
fprintf(stderr, "SELECT failed: %s \n", PQerrorMessage(conn));
fprintf(stderr, "maRequete= %s \n", maRequete);
PQclear(res);
exit_nicely(conn);
}

PQclear(res);
}

i++;
j++;
}

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

/* close the connection to the database and cleanup */
PQfinish(conn);

return 0;
}
0
kilian Messages postés 8731 Date d'inscription vendredi 19 septembre 2003 Statut Modérateur Dernière intervention 20 août 2016 1 527
1 juin 2007 à 10:12
Je ne sais pas c'est bizzare...
Tu es sûr que ça ne boucle pas un peu trop, nbPoints est bien initialisé?
0
SangJun_ Messages postés 17 Date d'inscription jeudi 31 mai 2007 Statut Membre Dernière intervention 28 septembre 2011
1 juin 2007 à 10:30
Non, pas de problème

Dans le code entier nbPoints est initialisé (c'est le nombre de points d'une LINE d'un SIG). De plus je code pour le moment en aillant pris un seul exemple où ce nombre est égal à 9 et c'est au 2nd tour de boucle (donc if (i==1) //Si c'est le premier segment, on crée le premier polygone ne pose pas de problème) que le problème survient.
0
kilian Messages postés 8731 Date d'inscription vendredi 19 septembre 2003 Statut Modérateur Dernière intervention 20 août 2016 1 527
1 juin 2007 à 10:34
Ben j'avoue que je sèche là....
0
SangJun_ Messages postés 17 Date d'inscription jeudi 31 mai 2007 Statut Membre Dernière intervention 28 septembre 2011
1 juin 2007 à 11:15
:-(
0
kilian Messages postés 8731 Date d'inscription vendredi 19 septembre 2003 Statut Modérateur Dernière intervention 20 août 2016 1 527
1 juin 2007 à 11:21
En apparence dans ton code je ne vois pas de problème.
Il y aurait peut être un segmentation fault par exemple si tu passais en paramètre une connexion ou une requête qui n'a pas été initialisée dans PQexec, mais il semblerais que ça ne soit pas le cas.

Juste avant la ligne critique qui génère l'erreur tu fais un affichage de ta requête, rajoute un
fflush(stdout);
pour être sûr que tout s'affiche bien avant l'erreur (bien que normalement le caractère "\n" s'en occupe tout seul).
Et puis avant ce fflush, fait un affichage du statut de ta connexion pour vérifier si tout va bien

=> if(PQstatus(conn) != CONNECTION_OK) ......
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
kilian Messages postés 8731 Date d'inscription vendredi 19 septembre 2003 Statut Modérateur Dernière intervention 20 août 2016 1 527
1 juin 2007 à 12:26
Il y a un problème avec ta connexion....

Déjà, pour éviter des problèmes qui pourraient venir d'on ne sait où, n'oublie pas d'inclure string.h et math.h

Rééssaie ensuite pour voir, je pense que l'erreur restera mais on ne sait jamais.
De toutes façon il faut que tu inclues ces fichiers.
0
SangJun_ Messages postés 17 Date d'inscription jeudi 31 mai 2007 Statut Membre Dernière intervention 28 septembre 2011
1 juin 2007 à 12:28
stdlib.h inclue math.h, non?

EDIT : inclusions faîtes => même résultat
0
kilian Messages postés 8731 Date d'inscription vendredi 19 septembre 2003 Statut Modérateur Dernière intervention 20 août 2016 1 527
1 juin 2007 à 12:29
Il semblerais que non puisque cos et sin ne sont pas reconnues.
De toutes façon c'est pas grave, même après plusieurs include, les fichiers d'en-tête des librairies standards ne se laisse pas inclure plusieurs fois...
0
SangJun_ Messages postés 17 Date d'inscription jeudi 31 mai 2007 Statut Membre Dernière intervention 28 septembre 2011
1 juin 2007 à 12:43
Cos et sin étaient reconnues puisque dans le premier tour de boucle j'obtenais des résultats faisant appel à ces fonctions.

M'enfin, je reste toujours avec ma connexion en échec sans aucun moyen de comprendre pourquoi :'(
0
kilian Messages postés 8731 Date d'inscription vendredi 19 septembre 2003 Statut Modérateur Dernière intervention 20 août 2016 1 527
1 juin 2007 à 12:57
Je ne saurais pas te dire...
Il y a un problème avec ta variable conn. Pourquoi ça je ne sais pas...
Tu libères les ressources comme il faut, peut être qu'il y a une erreur de requête que tu ne detectes pas et qui fait foirer ta connexion...
0
SangJun_ Messages postés 17 Date d'inscription jeudi 31 mai 2007 Statut Membre Dernière intervention 28 septembre 2011
1 juin 2007 à 13:29
1ier tour de boucle :
    {   strcpy(maRequete,"*** une requête ***");

        res = PQexec(conn,maRequete);

        if (PQresultStatus(res) != PGRES_TUPLES_OK)
        {
            fprintf(stderr, "SELECT failed: %s \n", PQerrorMessage(conn));
            fprintf(stderr, "maRequete= %s \n", maRequete);
            PQclear(res);
            exit_nicely(conn);
        }

        xA = atof(PQgetvalue(res, 0, 0));
        yA = atof(PQgetvalue(res, 0, 1));
        xB = atof(PQgetvalue(res, 0, 2));
        yB = atof(PQgetvalue(res, 0, 3));

        PQclear(res);

        if (i==1) //Si c'est le premier segment, on crée le premier polygone
        {
            strcpy(maRequete,"*** autre requête ***");


            res = PQexec(conn,maRequete);

            if (PQresultStatus(res) != PGRES_TUPLES_OK)
            {
                fprintf(stderr, "SELECT failed: %s \n", PQerrorMessage(conn));
                fprintf(stderr, "maRequete= %s \n", maRequete);
                PQclear(res);
                exit_nicely(conn);
            }

            PQclear(res);
        }else   // Sinon on fait une union avec le nouveau polygone
        {
            /*c'est un else donc on ne s'en préoccupe pas
        }

        i++;
        j++;
    }


2ème tour de boucle :
    {   strcpy(maRequete,"*** une requête ***");

        res = PQexec(conn,maRequete);

        if (PQresultStatus(res) != PGRES_TUPLES_OK)
        {
            fprintf(stderr, "SELECT failed: %s \n", PQerrorMessage(conn));
            fprintf(stderr, "maRequete= %s \n", maRequete);
            PQclear(res);
            exit_nicely(conn);
        }

        PQclear(res);

        if (i==1) //Si c'est le premier segment, on crée le premier polygone
        {
            //i=2
        }else   // Sinon on fait une union avec le nouveau polygone
        {
            strcpy(maRequete,"*** 3ème requête ***");

            /*Test pour l'erreur de PqExec*/
            fflush(stdout);

            printf("OK1\n");

            if(PQstatus(conn) != CONNECTION_OK)
            {
                printf("PQstatus(conn) != CONNECTION_OK\n");
            }
            printf("OK2\n",maRequete);

            res = PQexec(conn,maRequete);

            printf("OK2\n");

            if (PQresultStatus(res) != PGRES_TUPLES_OK)
            {
                fprintf(stderr, "SELECT failed: %s \n", PQerrorMessage(conn));
                fprintf(stderr, "maRequete= %s \n", maRequete);
                PQclear(res);
                exit_nicely(conn);
            }

            PQclear(res);
        }

        i++;
        j++;
    }
0
kilian Messages postés 8731 Date d'inscription vendredi 19 septembre 2003 Statut Modérateur Dernière intervention 20 août 2016 1 527
1 juin 2007 à 14:35
Essaie de faire des tests de PQstatus après les executions diverses de requête pour savoir d'où ça vient....
0
SangJun_ Messages postés 17 Date d'inscription jeudi 31 mai 2007 Statut Membre Dernière intervention 28 septembre 2011
1 juin 2007 à 16:00
J'ai fait des tests en changeant de taille ma variable maRequete (et d'une autre chaine que je concatène à maRequete) et l'erreur intervient plus tard.

La POO c'est tellement mieux :(
0
kilian Messages postés 8731 Date d'inscription vendredi 19 septembre 2003 Statut Modérateur Dernière intervention 20 août 2016 1 527
1 juin 2007 à 16:08
Rah...
0
SangJun_ Messages postés 17 Date d'inscription jeudi 31 mai 2007 Statut Membre Dernière intervention 28 septembre 2011
4 juin 2007 à 11:20
(post supprimé)
0
kilian Messages postés 8731 Date d'inscription vendredi 19 septembre 2003 Statut Modérateur Dernière intervention 20 août 2016 1 527
4 juin 2007 à 11:32
Euh, post supprimé?
Tu n'aimais pas ton message...?

En plus j'avais la réponse au problème :'(
0
SangJun_ Messages postés 17 Date d'inscription jeudi 31 mai 2007 Statut Membre Dernière intervention 28 septembre 2011
4 juin 2007 à 11:42
J'avais posté un message concernant une erreur dûe à une suite de requêtes reliées par des ";"
En exécutant chaque requête une à une, je n'ai plus d'erreur. Je me suis rendu compte que c'était assez stupide comme erreur donc j'ai supprimé le post.

Par contre, j'ai toujours le problème de la taille de la chapine de caractère (500000 c'est bien pratique mais c'est une valeur prise au hasard)
0
kilian Messages postés 8731 Date d'inscription vendredi 19 septembre 2003 Statut Modérateur Dernière intervention 20 août 2016 1 527
4 juin 2007 à 11:47
Ben, je t'ai expliqué comment allouer dynamiquement de la place pour une chaine par message privé.
Ya quelque chose que tu n'as pas compris?
0
SangJun_ Messages postés 17 Date d'inscription jeudi 31 mai 2007 Statut Membre Dernière intervention 28 septembre 2011
14 juin 2007 à 09:48
Maintenant c'est ok, sauf une erreur PostGIS
0