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 étrange sur un malloc


Sujet :

C

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre émérite Avatar de |PaRa-BoL
    Profil pro
    Inscrit en
    Novembre 2003
    Messages
    738
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France

    Informations forums :
    Inscription : Novembre 2003
    Messages : 738
    Par défaut Segfault étrange sur un malloc
    Bonjour,

    Je developpe en ce moment un server de Tchat compatible avec AJAX, enfin bref

    Le server étant fini et encore en beta je le laisse tourner et invite pas mal de monde à venir dessus.
    Je laisse donc un "ulimit -c unlimited" en cas d'un eventuel segfault.
    Après quelque jour sans problème le server a segfault.

    Je lance le fichier core qui a été généré :

    "gdb monprog -c core"

    Je fait un backtrace (bt) :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
     
    (gdb) bt
    #0  0xb7e8e060 in free () from /lib/tls/libc.so.6
    #1  0xb7e8fc4f in malloc () from /lib/tls/libc.so.6
    #2  0x0804afb2 in adduser (nick=0x807133e "yobakan", chan=0x8071346 "Ace", fdclient=4, ace_tables=0x804e008) at src/users.c:61
    #3  0x0804ab16 in raw_connect (param=0xbf86af30, fdclient=4, call_user=0x0, ace_tables=0x804e008) at src/raw.c:154
    #4  0x0804a8b4 in checkraw (cget=0x8070840, ace_tables=0x804e008) at src/raw.c:102
    #5  0x0804a417 in checkrecv (pSock=0x8071330 "GET", fdclient=4, ip=0xb7df603c "127.0.0.1", ace_tables=0x804e008) at src/kernel.c:124
    #6  0x08049a54 in sockroutine (port=6969, ace_tables=0x804e008) at src/sock.c:262
    #7  0x08048d72 in main (argc=1, argv=0xbf8750c4) at src/main.c:131
    Donc je me rend à la ligne 61 de users.c :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    nuser = (USERS *)malloc(sizeof(*nuser));
    Voici ma structure :

    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
     
    typedef struct USERS
    {
    	unsigned int fdclient;
    	unsigned int state;
    	unsigned int nraw;
     
    	char nick[MAX_NICK_LEN+1];
    	char sessid[33];
    	char chan[33];
    	char ip[32];
     
    	long int idle;
     
    	struct USERS *next;
    	struct USERS *prev;
     
    	struct RAW *rawhead;
    	struct RAW *rawfoot;
    } USERS;
    Qu'est ce qui a pu provoquer un segfault ici ? Un overflow ailleur ?

    Merci à vous

  2. #2
    Membre éprouvé
    Inscrit en
    Novembre 2002
    Messages
    120
    Détails du profil
    Informations forums :
    Inscription : Novembre 2002
    Messages : 120
    Par défaut
    Probablement plus de mémoire, ou quelque chose du genre (est-ce que tu as un moyen de voir l'utilisation mémoire de ton programme au fil du temps?). Tu dois revoir tes allocations et essayer de libérer la mémoire le plus tôt possible.

  3. #3
    Membre émérite Avatar de |PaRa-BoL
    Profil pro
    Inscrit en
    Novembre 2003
    Messages
    738
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France

    Informations forums :
    Inscription : Novembre 2003
    Messages : 738
    Par défaut
    Citation Envoyé par ShootDX
    Probablement plus de mémoire, ou quelque chose du genre (est-ce que tu as un moyen de voir l'utilisation mémoire de ton programme au fil du temps?). Tu dois revoir tes allocations et essayer de libérer la mémoire le plus tôt possible.
    Oui j'ai bien regardé la mémoire, tout est libéré, mon programme ne depasse 0.4% de mémoire. (De plus quand il s'agit de mémoire pleine, malloc retourne NULL mais ne segfault pas ?)

    Merci

  4. #4
    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
    La connaissance de la ligne 61 est très insuffisante pour te donner un coup de main. Il faudrait quand même un peu plus de code car certainement le problème qui se révèle ici vient d'une erreur ailleurs.

  5. #5
    Membre émérite Avatar de |PaRa-BoL
    Profil pro
    Inscrit en
    Novembre 2003
    Messages
    738
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France

    Informations forums :
    Inscription : Novembre 2003
    Messages : 738
    Par défaut
    Citation Envoyé par diogene
    La connaissance de la ligne 61 est très insuffisante pour te donner un coup de main. Il faudrait quand même un peu plus de code car certainement le problème qui se révèle ici vient d'une erreur ailleurs.
    gdb ne m'a donné que ca. Mon programme fait plusieur milliers de lignes et je n'ai pas réussi à reproduire le segfault :/

    Je suppose que si il c'est produit une fois il risque de revenir le fourbe !

    Mais la je vois que malloc a appelé free() (qui est celui qui a segfault), dans quel cas il fait ca ?

  6. #6
    Rédacteur

    Avatar de gege2061
    Femme Profil pro
    Administrateur de base de données
    Inscrit en
    Juin 2004
    Messages
    5 840
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 42
    Localisation : France

    Informations professionnelles :
    Activité : Administrateur de base de données

    Informations forums :
    Inscription : Juin 2004
    Messages : 5 840
    Par défaut
    Citation Envoyé par |PaRa-BoL
    Mais la je vois que malloc a appelé free() (qui est celui qui a segfault), dans quel cas il fait ca ?
    malloc qui appelle free, à part si la mémoire viens à manquer ça me parrait étrange (même dans ce cas là, comment il peux savoir quoi libérer )

    Donc si tu dis que tu ne déppasse pas les 0.4% d'utilisation (tu étais devant le moniteur système lors du segfault ?) ça viens surement d'une corruption de données. ça peux expliquer :
    1. Le plantage de free
    2. Le fait que malloc semble manquer de mémoire


    Citation Envoyé par =|PaRa-BoL
    Liste chainées, tables de hashages (une 10 aines ><), je teste à chaque fois les pointeurs NULL. Et des 100aines d'users se connects et se deconnects dans la journée. Je n'ai eu ce segfault que une seule fois.
    Peut être ai-je fait une erreure d'innatention quelque part.
    Mais pourquoi gdb m'indique t'il se malloc ?
    ça s'appel un comportement indéfini, ça porte bien son nom

  7. #7
    Expert confirmé
    Avatar de Mat.M
    Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2006
    Messages
    8 529
    Détails du profil
    Informations personnelles :
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Novembre 2006
    Messages : 8 529
    Par défaut
    c'est un peu incomplet ; tu obtients une fault segmentation parce que à un moment tu dois vouloir accéder à user->attribut et que user vaut 0x0000000 ( pointeur nul )
    Qu'est ce qui se passe si les connections sont perdues ?
    Si un user se déconnecte ?

    Citation Envoyé par |PaRa-BoL
    gdb ne m'a donné que ca. Mon programme fait plusieur milliers de lignes et je n'ai pas réussi à reproduire le segfault :/
    Y-a-til des listes chainées ?
    Je suis persuadé que cela vient de pointeurs qui sont nuls et que tu essaies d'adresser.....

  8. #8
    Membre émérite Avatar de |PaRa-BoL
    Profil pro
    Inscrit en
    Novembre 2003
    Messages
    738
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France

    Informations forums :
    Inscription : Novembre 2003
    Messages : 738
    Par défaut
    Citation Envoyé par Mat.M
    c'est un peu incomplet ; tu obtients une fault segmentation parce que à un moment tu dois vouloir accéder à user->attribut et que user vaut 0x0000000 ( pointeur nul )
    Qu'est ce qui se passe si les connections sont perdues ?
    Si un user se déconnecte ?


    Y-a-til des listes chainées ?
    Je suis persuadé que cela vient de pointeurs qui sont nuls et que tu essaies d'adresser.....
    Liste chainées, tables de hashages (une 10 aines ><), je teste à chaque fois les pointeurs NULL. Et des 100aines d'users se connects et se deconnects dans la journée. Je n'ai eu ce segfault que une seule fois.
    Peut être ai-je fait une erreure d'innatention quelque part.
    Mais pourquoi gdb m'indique t'il se malloc ?

    Merci

  9. #9
    Membre Expert
    Homme Profil pro
    Inscrit en
    Septembre 2006
    Messages
    2 963
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations forums :
    Inscription : Septembre 2006
    Messages : 2 963
    Par défaut
    Citation Envoyé par Mat.M
    c'est un peu incomplet ; tu obtients une fault segmentation parce que à un moment tu dois vouloir accéder à user->attribut et que user vaut 0x0000000 ( pointeur nul )
    Qu'est ce qui se passe si les connections sont perdues ?
    Si un user se déconnecte ?


    Y-a-til des listes chainées ?
    Je suis persuadé que cela vient de pointeurs qui sont nuls et que tu essaies d'adresser.....
    si le plantage venait du déréférencement d'un pointeur NULL, il aurait lieu plus près de l'instruction en cause, alors qu'ici il a lieu à l'intérieur de la librairie malloc… (quoique le free(NULL) peut provoquer ce genre de choses …)

    autres possibilités :
    ou des écritures au-delà de la taille d'un bloc alloué qui corrompent le heap
    ou des écritures dans un bloc après qu'il ait été libéré par free()…
    ou un double free()…
    ou …
    les manières de corrompre la mémoire sont infinies…

    quant un plantage "dans" free()… : ne pas oublier que gdb rapporte le symbole de la fonction la plus proche en fonction du PC et de la table des symboles… il est plus probable qu'en fait vous êtes dans du code de bas niveau optimisé en assembleur qui se trouve aux alentours de free()… ce qui laisse penser que ce qui se plante est en fait le "crawling" dans la chaîne des blocs libres…

    si malloc_debug() est disponible dans votre environnement, activez-le ou si une version debug de libc est disponible, liez votre programme à cette version et activez les checks du heap…
    (attention cela va ralentir le programme…)

  10. #10
    Expert confirmé
    Avatar de Mat.M
    Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2006
    Messages
    8 529
    Détails du profil
    Informations personnelles :
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Novembre 2006
    Messages : 8 529
    Par défaut
    Citation Envoyé par |PaRa-BoL
    Oui j'ai bien regardé la mémoire, tout est libéré, mon programme ne depasse 0.4% de mémoire. (De plus quand il s'agit de mémoire pleine, malloc retourne NULL mais ne segfault pas ?)
    Merci
    malloc sans free ne provoque pas de fault segmentation.
    Tu peux très bien déclarer un malloc faire une allocation finir le programme.
    C'est intégre au niveau du code machine.
    Par contre tu auras des fuites de mémoires....

  11. #11
    Membre émérite Avatar de |PaRa-BoL
    Profil pro
    Inscrit en
    Novembre 2003
    Messages
    738
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France

    Informations forums :
    Inscription : Novembre 2003
    Messages : 738
    Par défaut
    Citation Envoyé par Mat.M
    malloc sans free ne provoque pas de fault segmentation.
    Tu peux très bien déclarer un malloc faire une allocation finir le programme.
    C'est intégre au niveau du code machine.
    Par contre tu auras des fuites de mémoires....
    Je libère tout les malloc que j'utilise à un moment ou un autre :/

  12. #12
    Expert confirmé
    Avatar de Mat.M
    Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2006
    Messages
    8 529
    Détails du profil
    Informations personnelles :
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Novembre 2006
    Messages : 8 529
    Par défaut
    Citation Envoyé par |PaRa-BoL
    Je libère tout les malloc que j'utilise à un moment ou un autre :/
    tu as l'impression au niveau du code mais qu'en est-il en réalité ??
    Le programme est-il multi processus ?
    Dans le cas contraire il faut que cela soit en multithreading sinon cela ne peut pas fonctionner correctement.
    C'est peut-être un problème de synchros des processus.

  13. #13
    Membre Expert
    Avatar de Gruik
    Profil pro
    Développeur Web
    Inscrit en
    Juillet 2003
    Messages
    1 566
    Détails du profil
    Informations personnelles :
    Âge : 42
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Juillet 2003
    Messages : 1 566
    Par défaut
    Citation Envoyé par ShootDX
    Probablement plus de mémoire, ou quelque chose du genre (est-ce que tu as un moyen de voir l'utilisation mémoire de ton programme au fil du temps?). Tu dois revoir tes allocations et essayer de libérer la mémoire le plus tôt possible.
    Ce n'est pas que mon experience est exemplaire, mais un malloc qui echoue par manque de memoire je n'ai jamais vu ça de ma vie, c'est tellement excessivement rare comparé à la cause suivante :
    Un depassement ou un double free qui corrompt certaines données internes à la libc faisant echouer aleatoirement des malloc ou des free

  14. #14
    Rédacteur

    Avatar de gege2061
    Femme Profil pro
    Administrateur de base de données
    Inscrit en
    Juin 2004
    Messages
    5 840
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 42
    Localisation : France

    Informations professionnelles :
    Activité : Administrateur de base de données

    Informations forums :
    Inscription : Juin 2004
    Messages : 5 840
    Par défaut
    Citation Envoyé par Gruik
    Ce n'est pas que mon experience est exemplaire, mais un malloc qui echoue par manque de memoire je n'ai jamais vu ça de ma vie, c'est tellement excessivement rare comparé à la cause suivante :
    Un depassement ou un double free qui corrompt certaines données internes à la libc faisant echouer aleatoirement des malloc ou des free
    C'est vrai, par exemple sous linux cela n'arrive jamais puisque le processus qui a fait la demande refusée est tué. Mais c'est sous Linux...

  15. #15
    Membre Expert
    Homme Profil pro
    Inscrit en
    Septembre 2006
    Messages
    2 963
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations forums :
    Inscription : Septembre 2006
    Messages : 2 963
    Par défaut
    Citation Envoyé par gege2061
    C'est vrai, par exemple sous linux cela n'arrive jamais puisque le processus qui a fait la demande refusée est tué. Mais c'est sous Linux...
    pas tout à fait correct…
    le programme est tué lors d'un malloc si le kernel ne peut étendre la mémoire déjà allouée au processsus…

    par contre malloc peut renvoyé NULL s'il peut étendre la mémoire MAIS sans garantie que les pages puissent effectivement être allouées plus tard…
    ce qui est peut être "rare"…
    toutefois cela suffit à justifier de tester si malloc renvoit NULL…
    la condition de rareté dépendant de l'environnement… notamment en 64 bits, les comportements risquent d'être différents…

    voir (en anglais)

  16. #16
    Expert éminent
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 395
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 395
    Par défaut
    Pu***n, c'est gore

    Comment peut-on oser proposer ça dans un kernel qui a vocation à exclure Win32 et se répandre librement et gratuitement ?
    Et à quoi sert de spécifier que malloc() est supposé retourner NULL, si c'est pour tuer un process à la place?
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  17. #17
    Expert éminent
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 68
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Par défaut
    Citation Envoyé par |PaRa-BoL
    Qu'est ce qui a pu provoquer un segfault ici ? Un overflow ailleur ?
    C'est tout à fait possible. Mais comme ton code est parfaitement bien conçu, donc modulaire, tu vas pouvoir repasser tous les tests unitaires et isoler le coupable facilement...

  18. #18
    Membre émérite Avatar de |PaRa-BoL
    Profil pro
    Inscrit en
    Novembre 2003
    Messages
    738
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France

    Informations forums :
    Inscription : Novembre 2003
    Messages : 738
    Par défaut
    Citation Envoyé par Emmanuel Delahaye
    C'est tout à fait possible. Mais comme ton code est parfaitement bien conçu, donc modulaire, tu vas pouvoir repasser tous les tests unitaires et isoler le coupable facilement...
    c'est une affirmation moqueuse ?

    Je n'aurai pas cette prétention. Ce n'est qu'un petit projet personnel, je suis encore novice je pense avoir fait de mon mieux pour le moment :/ Mais je ne pense pas pouvoir tout reprendre à part.
    En disant que je ne pensait pas avoir de pointeur NULL ou que j'avait free() tout mes buffers, je ne voulais pas dire par la que c'était bien conçu, c'est juste que j'ai vérifié 500x :/

  19. #19
    Expert confirmé
    Avatar de Mat.M
    Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2006
    Messages
    8 529
    Détails du profil
    Informations personnelles :
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Novembre 2006
    Messages : 8 529
    Par défaut
    1-je suis sceptique sur le code
    udeco = seek_user_fd(poll_list[i].fd, ace_tables);
    if (udeco != NULL && udeco->state == ALIVE) {
    udeco->state = ADIED;
    }
    si udeco retourné par seek_user_fd vaut 0 ou NULL c'est le plantage garanti.
    udeco=NULL et udeco->state vaut NULL donc tu ne peux pas adresser state sinon c'est le plantage garanti

    2-
    Citation Envoyé par |PaRa-BoL
    Qu'est ce qui ne fonctionnerai jamais correctement ?
    la synchronisation des différents événements , envoi /réception de données connection /déconnection utilisateur.

  20. #20
    Membre émérite Avatar de |PaRa-BoL
    Profil pro
    Inscrit en
    Novembre 2003
    Messages
    738
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France

    Informations forums :
    Inscription : Novembre 2003
    Messages : 738
    Par défaut
    si udeco retourné par seek_user_fd vaut 0 ou NULL c'est le plantage garanti.
    udeco=NULL et udeco->state vaut NULL donc tu ne peux pas adresser state sinon c'est le plantage garanti
    Bah non regarde je verifi dans ma condition.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    if (udeco != NULL && udeco->state == ALIVE) {
    Et si udeco est NULL il essayera pas d'évaluer la deuxieme condition.


    la synchronisation des différents événements , envoi /réception de données connection /déconnection utilisateur.
    Mon t'chat n'est pas en streaming (oui il est prevu pour un client AJAX).

    Et quand bien même il sagirais d'un t'chat en streaming, je ne vois pas en quoi c'est génant que ca soit monothread à part des problèmes de lag.
    En effet si une personne se connect il executera le code et si une personne se deconnect en même temps elle est automatiquement mise en attente avec le system poll() et vu qu'il n'ya qu'un seul thread forcement 1 seule chose à la fois donc pas de probleme de synchronisation. Enfin du moins c'est comme ca que j'imagine la chose, je vois pas autrement Oo Et à l'inverse un systeme multi thread il faut bien veillé à proteger ces données partagées (MuTeX)

Discussions similaires

  1. Segfault sur un malloc[Contourné]
    Par Alfrodull dans le forum Débuter
    Réponses: 3
    Dernier message: 08/01/2012, 17h27
  2. [MySQL] pb étrange sur mon site!
    Par mastercartman dans le forum PHP & Base de données
    Réponses: 3
    Dernier message: 23/03/2006, 18h38
  3. [xp] problème étrange sur le système de fichiers
    Par Huntress dans le forum Windows XP
    Réponses: 4
    Dernier message: 05/03/2006, 20h15
  4. blocage bizarre sur un malloc
    Par gilux dans le forum C
    Réponses: 13
    Dernier message: 24/01/2006, 09h36
  5. Erreur étrange sur recvfrom
    Par Gore dans le forum Développement
    Réponses: 2
    Dernier message: 17/02/2005, 12h22

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