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 :

segfault sorti de nul part


Sujet :

C

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Inscrit en
    Septembre 2010
    Messages
    22
    Détails du profil
    Informations forums :
    Inscription : Septembre 2010
    Messages : 22
    Par défaut segfault sorti de nul part
    Bonjour,
    j'ai un souci avec cette fonction qui me renvoit une erreur de segmentation:
    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
     
    char* convert(integer a)
    {
      char *stab=NULL;
       printf("convert\n");
      stab=(char*)malloc(sizeof(unsigned long int));
     
      if(stab==NULL)
      {
        printf("failure in memory allocation %s/%d\n",__FILE__,__LINE__);
        exit(0);
      }
      sprintf(stab,"%ld",a);
      return stab;
    }
    Elle marche nikel la plupart du temps dans mon code, mais lors d'un des appels elle me renvoit une segfault au niveau de la ligne
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
     stab=(char*)malloc(sizeof(unsigned long int));
    et je vois pas d'où ca vient.. La fonction est censé prendre un entier en input et me renvoyer une chaine de caracteres correspondante.
    J'ai écrit une connerie?

  2. #2
    Invité(e)
    Invité(e)
    Par défaut
    Bonjour,

    Que valent les entiers que tu convertis ?

    En écrivant sizeof(unsigned long int) tu réserves (je pense) 8 octets, soit de la place pour 7 caractères plus le '\0'.

    Si ton entier à convertir est au moins égal à 10 000 000, tu va écrire où tu n'a pas le droit (sprintf(stab,"%ld",a); ) mais l'erreur peut n'être levée qu'après un certain temps. (On parle de comportement indéfini).

    Pour allouer un espace suffisant, tu peux compter le nombre de caractères nécessaires au stockage d'un entier :

    On peut utiliser le logarithme pour ça :
    rappel :
    il y a 2 chiffres dans 10 et log(10) = 1,
    il y a 2 chiffres dans 50 et log(50) = 1.7,
    il y a 3 chiffres dans 100 et log(100)= 2
    Il faut donc ajouter 1 au logarithme d'une nombre pour savoir avec combien de chiffres il s'écrit. Comme on est en C, on pense aussi à allouer de l'espace pour le '\0'.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    size_t sz;
     
    if(a > 0) {
       /* calcul du log décimal de a  */
       sz = (log(a) / log(10));
       sz += 2;
    } else {
        /* a prendre en compte (cas nul et négatif) */
    }
     
    stab = malloc(sz);
     
    ...

  3. #3
    Membre averti
    Inscrit en
    Septembre 2010
    Messages
    22
    Détails du profil
    Informations forums :
    Inscription : Septembre 2010
    Messages : 22
    Par défaut
    Merci, j'ai apporté les corrections que tu m'as conseillé mais sans résultats..
    Se pourrait il que cela vienne du fait que je ne libere pas la mémoire? Du coup ca marche au debut jusqu'au moment où ca ne passe plus? Et en ce cas, où placer mon free(stab)? Sachant que je retourne stab, je ne peux pas le placer avant return?

    edit:ce qui m'embete surtout c'est que l'erreur vienne de l'allocation de mémoire, et pas d'un éventuel depassement ulterieur (visiblement en tout cas)

  4. #4
    Membre Expert
    Profil pro
    Inscrit en
    Août 2006
    Messages
    1 104
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2006
    Messages : 1 104
    Par défaut
    Rien à voir avec ton problème, mais , ce n'est pas propre.

  5. #5
    Invité(e)
    Invité(e)
    Par défaut
    Citation Envoyé par nocta Voir le message
    Merci, j'ai apporté les corrections que tu m'as conseillé mais sans résultats..
    Se pourrait il que cela vienne du fait que je ne libere pas la mémoire? Du coup ca marche au debut jusqu'au moment où ca ne passe plus? Et en ce cas, où placer mon free(stab)? Sachant que je retourne stab, je ne peux pas le placer avant return?
    Si tu ne libère pas la mémoire dans convert, c'est à celui qui appelle convert de libérer la mémoire.

    Si tu ne libères pas la mémoire, tu auras une fuite mémoire qui au pire fera échouer les appels à malloc, mais pas un segfault.

    Tu dois corrompre la mémoire ailleurs dans le programme. (dépassement de tableau ...)

    S'il n'est pas trop gros, peux tu poster un peu plus de ton programme.

    Au passage, si tu es en C, la cast (char *) est inutile.

    Sinon, un peu de lecture :
    http://fr.wikipedia.org/wiki/Erreur_de_segmentation
    http://www.velocityreviews.com/forum...ion-fault.html

  6. #6
    Membre averti
    Inscrit en
    Septembre 2010
    Messages
    22
    Détails du profil
    Informations forums :
    Inscription : Septembre 2010
    Messages : 22
    Par défaut
    Si tu ne libère pas la mémoire dans convert, c'est à celui qui appelle convert de libérer la mémoire.
    Je dois alors (dans mon exemple), redéclarer stab dans la fonction qui appele convert?
    Pour pouvoir le liberer par la suite?

    Je te poste la fonction qui appele convert(), je ne peux pas te poster tout le code il est vraiment trop long..

    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
    39
    40
    41
    42
    43
    44
    45
    46
    long long int multiplicative_inverse(integer a, integer b)
    {
     
    integer a0=a;
    integer b0=b;
    long long int t0=0;
    long long int t=1;
     
    char* s_a0=convert(a0);
    char* s_b0=convert(b0);
    char s_q[SZ_MAX];
     
    bigDivision(s_b0,s_a0,s_q);
     
    long long int q=strtoint(s_q);
    char s_r[SZ_MAX];
    char s_tmp[SZ_MAX];
    bigMultiplication(s_q,s_a0,s_tmp);
    bigSubstraction(s_b0,s_tmp,s_r);
    long long int r=strtoint(s_r);
    while(r>0)
    {
      long long int temp=t0-q*t;
      t0=t;
      t=temp;
      b0=a0;
      a0=r;
      q=b0/a0;
      r=b0-q*a0;
    }
    if(a0!=1)
    {
      printf("No inverse\n");
      printf("Error in eucliExt\n");
      return -1;
    }
    {
      while(t<0)
      {
        t=t+b;
      }
      t=fmod(t,b);
     
      return t;
    }
    }
    C'est une fonction qui doit calculer l'inverse multiplicatif, modulo b, de a.
    biDivision et bigModulo sont des fonctions qui traitent des grands nombres. Ils prennent en paramètre des chaines de caractere, d'où l'utilité de convert().

    Merci pour la lecture! (j'ai déjà lu l'article wikipedia).

    @jeroman un 'return 0' par exemple serait il plus judicieux?

  7. #7
    Membre Expert
    Profil pro
    Inscrit en
    Août 2006
    Messages
    1 104
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2006
    Messages : 1 104
    Par défaut
    @jeroman un 'return 0' par exemple serait il plus judicieux?
    Un "return NULL;" (la fonction renvoie un pointeur). Par contre, il faut que la fonction appelante gère aussi un éventuel "NULL" retourné.
    Le problème avec les "exit", c'est la fermeture sauvage du programme, avec toutes les conséquences que cela entraîne, comme par exemple la non libération de toutes les allocations mémoire précédentes effectuées, etc. Et il y a aussi un problème plus "philosophique" : lorsqu'une fonction échoue, il faut le faire savoir à la fonction appelante, qui doit gérer le problème, ou faire gérer par celle qui l'a appelée, etc. Disons que c'est plus propre, ça organise mieux le code.

  8. #8
    Expert confirmé
    Avatar de diogene
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Juin 2005
    Messages
    5 761
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2005
    Messages : 5 761
    Par défaut
    Et en ce cas, où placer mon free(stab)?
    Lorsque tu n'as plus besoin du contenu du buffer alloué.
    Sachant que je retourne stab, je ne peux pas le placer avant return?
    Surtout pas, tu détruirais le buffer.
    un 'return 0' par exemple serait il plus judicieux?
    Le plus judicieux est un return NULL puisque tu renvoies un pointeur. A charge de celui qui appelle la fonction de tester si la valeur retournée est bien différente de NULL.


    Il est possible d'obtenir le nombre de char nécessaire par un premier appel à snprintf() :
    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
    char* convert(integer a)
    {
      char * stab;
      int i = snprintf(NULL,0,"%ld",a);
      stab = malloc(i+1);
      if(stab != NULL) snprintf(stab,i+1,"%ld",a);
      return stab;
    }
    int main(void)
    {
      char *p= convert(1234567890);
      if(p!=NULL) 
      {
         printf("%s",p);
         free(p);
      }
      else printf("Erreur d'allocation");
      return 0;
    }

Discussions similaires

  1. un envoi de mail PHP qui ne marche PRESQUE nul part
    Par laurentSc dans le forum Langage
    Réponses: 15
    Dernier message: 02/05/2011, 18h09
  2. [PHP 5.4] Erreur sortie de nulle part
    Par thebarbarius dans le forum Langage
    Réponses: 7
    Dernier message: 12/03/2010, 05h06
  3. Réponses: 9
    Dernier message: 04/06/2009, 16h59
  4. Problème d'événements sortis de nul part
    Par coldrink dans le forum SDL
    Réponses: 1
    Dernier message: 23/05/2009, 18h25
  5. [JTreeTable/JTable] getValueAt appelée nul part
    Par Zanton dans le forum Composants
    Réponses: 9
    Dernier message: 02/06/2006, 14h16

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