IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C Discussion :

seg fault avec gmp


Sujet :

C

  1. #1
    Nouveau Candidat au Club
    Inscrit en
    Mai 2010
    Messages
    4
    Détails du profil
    Informations forums :
    Inscription : Mai 2010
    Messages : 4
    Points : 1
    Points
    1
    Par défaut seg fault avec gmp
    alors voilà je suis nouvelle sur ce forum et j'ai une segfault que j'arrive pas à supprimer.
    je m'explique, je fais un projet pour lequel je dois manipuler de très grands nombres (ex : 230979485048261039076034528529086839797) j'utilise donc la librairie gmp.
    mon erreur est la suivante : j'ai un très grand entier (type mpz_t) que je dois convertir en binaire (dans mon cas, créer un tableau de 128 bits), ma fonction de conversion fonctionne parfaitement mais à la fin j'ai une segfault qui apparait alors que le résultat est correct (pour moi elle est là juste pour le fun ). j'ai donc utilisé gdb pour comprendre un peu mieux l'erreur et voilà le résultat :
    Program received signal SIGSEGV, Segmentation fault.
    0x001befa8 in ?? () from /lib/tls/i686/cmov/libc.so.6
    (gdb) up
    #1 0x001bf0cf in exit () from /lib/tls/i686/cmov/libc.so.6
    (gdb) up
    #2 0x001a6b5e in __libc_start_main () from /lib/tls/i686/cmov/libc.so.6
    (gdb) up
    #3 0x080489a1 in _start () at ../sysdeps/i386/elf/start.S:119
    119 ../sysdeps/i386/elf/start.S: Aucun fichier ou dossier de ce type.
    in ../sysdeps/i386/elf/start.S
    Current language: auto
    The current source language is "auto; currently asm".
    j'avoue que j'ai jamais compris grand chose à gdb, je l'utilise pour situer la ligne de code fautive mais là il m'aide pas du tout !

    voilà mon programme qui fait la conversion :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
     
    void gmp2bin(mpz_t n, int size, int* bin_tab){
            int i=size-1;
            mpz_t nb;
            mpz_init_set(nb,n);
     
            if(mpz_cmp_ui(nb,0)==0){
                    while(i>=0){
                            bin_tab[i] = 0;
                            i--;
                    }
            }
            else{
                    while(mpz_cmp_ui(nb,0)>0){
                           if(mpz_even_p(nb) == 0){
                                    bin_tab[i] = 1;
                                    mpz_sub_ui(nb,nb,1);
                                    mpz_divexact_ui(nb,nb,2);
                            }
                            else{
                                    bin_tab[i] = 0;
                                    mpz_divexact_ui(nb,nb,2);
                            }
                            i--;
                    }
                    while(i>=0){
                            bin_tab[i] = 0;
                            i--;
                    }
            }
    }
    voilà j'espère que j'ai été assez claire et que quelqu'un pourra me venir en aide !

    merci d'avance !

  2. #2
    Membre actif Avatar de Grulim
    Profil pro
    Inscrit en
    Juillet 2004
    Messages
    234
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2004
    Messages : 234
    Points : 288
    Points
    288
    Par défaut
    Peux-tu préciser l'OS (linux?), le compilo (gcc?), sa version, les options de compilation et aussi la version de gdb ?

  3. #3
    Nouveau Candidat au Club
    Inscrit en
    Mai 2010
    Messages
    4
    Détails du profil
    Informations forums :
    Inscription : Mai 2010
    Messages : 4
    Points : 1
    Points
    1
    Par défaut
    alors je suis sous ubuntu avec gcc version 4.4.1, avec comme options : -pg -g -Wall -W -pedantic -O0 et la version de gdb est la 7.0-ubuntu

    (merci j'avais pas pensé à préciser tout ça)

  4. #4
    Membre actif Avatar de Grulim
    Profil pro
    Inscrit en
    Juillet 2004
    Messages
    234
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2004
    Messages : 234
    Points : 288
    Points
    288
    Par défaut
    un SEG FAULT peut résulter (entre autre) d'un dépassement de borne dans un tableau.
    Comment est appelée la fonction gmp2bin et plus précisément, comment sont initialisés les paramètres size et bin_tab ?

  5. #5
    Nouveau Candidat au Club
    Inscrit en
    Mai 2010
    Messages
    4
    Détails du profil
    Informations forums :
    Inscription : Mai 2010
    Messages : 4
    Points : 1
    Points
    1
    Par défaut
    alors voilà c'était vraiment juste pour tester donc c'est pas bien compliqué.
    comme ma fonction marchait malgré ma segfault j'ai continué en l'utilisant dans mon projet et là plus de segfault donc je pense que tu as raison, c'est au moment de la tester que je me plante.

    même si ça marche je veux bien que tu me dise ou j'ai fait l'erreur parce que je pense que je pourrais la refaire ailleurs...

    en tout cas merci de ton aide !

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    mpz_t res;
    mpz_set_ui(res,17);
    int* tab = malloc(20*sizeof(int));
     
    gmp2bin(res,20,tab);
     
    for(j=0;j<20;j++) printf("%i",tab[j]);
    printf("\n");

  6. #6
    Membre actif Avatar de Grulim
    Profil pro
    Inscrit en
    Juillet 2004
    Messages
    234
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2004
    Messages : 234
    Points : 288
    Points
    288
    Par défaut
    Je ne connais pas la librairie gmp donc je ne me prononcerais pas sur son utilisation (correcte ou non) .
    Pour le reste, je vois une seule chose :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
                    while(mpz_cmp_ui(nb,0)>0){
                           if(mpz_even_p(nb) == 0){
                                    bin_tab[i] = 1;
                                    mpz_sub_ui(nb,nb,1);
                                    mpz_divexact_ui(nb,nb,2);
                            }
                            else{
                                    bin_tab[i] = 0;
                                    mpz_divexact_ui(nb,nb,2);
                            }
                            i--;
                    }
    Es-tu sure de sortir de cette boucle à temps ? cad avant que i < 0...

  7. #7
    Membre actif Avatar de Grulim
    Profil pro
    Inscrit en
    Juillet 2004
    Messages
    234
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2004
    Messages : 234
    Points : 288
    Points
    288
    Par défaut
    Si tu me permets de te donner quelques conseils amicaux :
    1. Dans tes boucle while, je préfèrerais que tu utilises la pré-incrémentation/décrémentation plutôt que la post.
    2. ton code peut être simplifié en utilisant un memset.
    3. un tableau de int pour stocker des 0 et des 1, pourquoi pas un tableau de char ou d'unsigned char plutôt ?

  8. #8
    Nouveau Candidat au Club
    Inscrit en
    Mai 2010
    Messages
    4
    Détails du profil
    Informations forums :
    Inscription : Mai 2010
    Messages : 4
    Points : 1
    Points
    1
    Par défaut
    merci pour tes conseils, c'est toujours bon à prendre !
    par contre je comprends pas pourquoi tu préfères que je mette le "i--", dans mon cas, au début, j'ai toujours eu l'habitude de le mettre à la fin et je trouve que c'est plus lisible. ensuite memset je connaissais pas (j'ai appris le C toute seule alors il y a plein de fonctions que je connais pas et j'ai souvent tendance à ré-inventer la roue ) et pour mon tableau je préfère les int, je trouve que c'est plus pratique à gérer. mais merci quand même pour tes suggestions !

  9. #9
    Membre actif Avatar de Grulim
    Profil pro
    Inscrit en
    Juillet 2004
    Messages
    234
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2004
    Messages : 234
    Points : 288
    Points
    288
    Par défaut
    Citation Envoyé par kkouet' Voir le message
    merci pour tes conseils, c'est toujours bon à prendre !
    A ton service
    Citation Envoyé par kkouet'
    par contre je comprends pas pourquoi tu préfères que je mette le "i--", dans mon cas, au début, j'ai toujours eu l'habitude de le mettre à la fin et je trouve que c'est plus lisible
    Dans ton cas, il n'y aura pas de différence, puisque tu utilises un type simple (int) mais pour des types plus compliqués, il se pourrait (note le conditionnel) que ton compilo ne sache pas optimiser ton code. C'est plus flagrant en C++.
    Citation Envoyé par kkouet'
    ensuite memset je connaissais pas (j'ai appris le C toute seule alors il y a plein de fonctions que je connais pas et j'ai souvent tendance à ré-inventer la roue )
    Utilise les fonctions du Runtime C, tu verras ça améliorera la clarté de ton code (pour les autres) et tu arriveras au même résultat plus vite (si, si je t'assure )
    Citation Envoyé par kkouet'
    et pour mon tableau je préfère les int, je trouve que c'est plus pratique à gérer.
    Ah bon, pourquoi ?
    Citation Envoyé par kkouet'
    mais merci quand même pour tes suggestions !
    Au plaisir.

    Tu n'as pas répondu à ma question :
    Es-tu sure de sortir de cette boucle à temps ? cad avant que i < 0...

  10. #10
    Membre actif Avatar de Grulim
    Profil pro
    Inscrit en
    Juillet 2004
    Messages
    234
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2004
    Messages : 234
    Points : 288
    Points
    288
    Par défaut
    voila le code un peu remanié:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    void gmp2bin2(mpz_t n, int size, int* bin_tab){
        int i;
        mpz_t nb;
     
        memset(bin_tab, 0, size*sizeof(bin_tab[0]));
     
        if(mpz_cmp_ui(nb,0)!=0){
            mpz_init_set(nb,n);
            for(int i=size-1; i > 0 && mpz_cmp_ui(nb,0)>0; --i) {
               if(mpz_even_p(nb) == 0){
                    bin_tab[i] = 1;
                    mpz_sub_ui(nb,nb,1);
                    mpz_divexact_ui(nb,nb,2);
                }
                else{
                    mpz_divexact_ui(nb,nb,2);
                }
            }
        }
    }
     
     
     
    int main()
    {
        mpz_t res;
        int* tab = malloc(20*sizeof(int));
        if(tab != NULL) {
            mpz_set_ui(res,17);
            gmp2bin(res,20,tab);
     
            for(j=0;j<20;j++) printf("%i",tab[j]);
            printf("\n");
     
            free(tab);
        }
        return 0;
    }

  11. #11
    Membre actif Avatar de ironzorg
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    288
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2006
    Messages : 288
    Points : 245
    Points
    245
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    memset(bin_tab, 0, size*sizeof(bin_tab[0]));
    Rien a voir avec le topic mais c'est un raccourci sympa a utiliser: pour recuperer la taille d'un tableau a une dimension, on peut connaitre sa taille grace a la macro si dessous (pour economiser un argument dans une fonction, en l'occurence `size').

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    #define T_SIZE(x) (sizeof(x) / sizeof(*x))
    HTH.

  12. #12
    gl
    gl est déconnecté
    Rédacteur

    Homme Profil pro
    Inscrit en
    Juin 2002
    Messages
    2 165
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Isère (Rhône Alpes)

    Informations forums :
    Inscription : Juin 2002
    Messages : 2 165
    Points : 4 637
    Points
    4 637
    Par défaut
    Citation Envoyé par Grulim Voir le message
    Dans ton cas, il n'y aura pas de différence, puisque tu utilises un type simple (int) mais pour des types plus compliqués, il se pourrait (note le conditionnel) que ton compilo ne sache pas optimiser ton code. C'est plus flagrant en C++.
    C'est certes vrai en C++ (surcharge des opérateurs sur les classes utilisateur).

    Mais en C, sur un compilateur un minimum efficace, cela fait longtemps que ce n'est plus vrai, puisque, pour faire simple, on ne peut appeler les opérateurs d'incrément et de décrément que sur des types simples.

    Citation Envoyé par ironzorg Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    memset(bin_tab, 0, size*sizeof(bin_tab[0]));
    Rien a voir avec le topic mais c'est un raccourci sympa a utiliser: pour recuperer la taille d'un tableau a une dimension, on peut connaitre sa taille grace a la macro si dessous (pour economiser un argument dans une fonction, en l'occurence `size').

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    #define T_SIZE(x) (sizeof(x) / sizeof(*x))
    C'est vrai pour un tableau statique. Dans le code de Grulim, bin_tab est un pointeur, ce n'est donc pas utilisable ici.

    D'une manière générale, lorsque tu passes le tableau en paramètre d'une fonction, pour la fonction en question ce n'est qu'un pointeur et cette astuce n'est donc pas applicable, il est nécessaire de fournir la taille en paramètre de la fonction.

  13. #13
    Membre actif Avatar de Grulim
    Profil pro
    Inscrit en
    Juillet 2004
    Messages
    234
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2004
    Messages : 234
    Points : 288
    Points
    288
    Par défaut
    Citation Envoyé par gl
    Mais en C, sur un compilateur un minimum efficace, cela fait longtemps que ce n'est plus vrai, puisque, pour faire simple, on ne peut appeler les opérateurs d'incrément et de décrément que sur des types simples.
    Pourrais-tu préciser ? Comme type non-simple, je pensais aux enums.
    Est-ce les compilos efficaces qui signalent (interdisent?) cela, ou la norme (C99?) ?

    Je travaille actuellement avec vieux compilo C (gcc 3.4.6 20060404), est-il concerné ?

    NB: Ce sont de vrais questions, pas une vaine tentative de pinaillage .

  14. #14
    gl
    gl est déconnecté
    Rédacteur

    Homme Profil pro
    Inscrit en
    Juin 2002
    Messages
    2 165
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Isère (Rhône Alpes)

    Informations forums :
    Inscription : Juin 2002
    Messages : 2 165
    Points : 4 637
    Points
    4 637
    Par défaut
    Citation Envoyé par Grulim Voir le message
    Pourrais-tu préciser ? Comme type non-simple, je pensais aux enums.
    En C, un enum est grosso-modo un entier. Donc pas de soucis particulier.

Discussions similaires

  1. Réponses: 2
    Dernier message: 10/04/2006, 19h40
  2. [fclose] erreur de fermeture (seg fault)
    Par Goundy dans le forum C
    Réponses: 17
    Dernier message: 06/04/2006, 13h16
  3. Segmentation fault avec glCompressedTexImage2DARB
    Par patbier dans le forum OpenGL
    Réponses: 5
    Dernier message: 12/12/2005, 10h32
  4. probleme de valeur retournée et seg fault
    Par florent_de_brest dans le forum C
    Réponses: 5
    Dernier message: 04/12/2005, 16h28
  5. Pb segmentation fault avec glutinit()
    Par pipistrelle dans le forum GLUT
    Réponses: 2
    Dernier message: 17/11/2004, 23h17

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo