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

SL & STL C++ Discussion :

Segfault sur contructeur de string


Sujet :

SL & STL C++

  1. #1
    Membre éprouvé
    Profil pro
    Inscrit en
    Juin 2006
    Messages
    107
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2006
    Messages : 107
    Par défaut Segfault sur contructeur de string
    Bonjour,
    c'est un peu découragé que je poste (après avoir passé des heures là dessus), en espérant que quelqu'un voit le problème (qui doit être évident ...).

    Bon, j'ai un petit programme avec plusieurs threads (pour l'heure deux, mais le deuxième thread n'a pas le temps de démarrer), dont les fonctions "main" sont placées dans des libraries différentes.

    Le chargement des lib, et des symboles de fonctions se passe bien, et j'ai le temps d'appeler la fonction init de la première lib.
    À l'appel de la fonction start de la première lib, j'ai droit à un segfault ici :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    datas->log.setLogName("spv-numeroteur");
    avec comme sortie de valgrind :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    Process terminating with default action of signal 11 (SIGSEGV)
      Access not within mapped region at address 0xFFFFFFF4
        at 0x4234E58: std::string::assign(char const*, unsigned) (in /usr/lib/libstdc++.so.6.0.9)
       by 0x4234FC4: std::string::operator=(char const*) (in  usr/lib/libstdc++.so.6.0.9)
        by 0x805E0FF: Log::setLogName(char const*) (Log.hpp:143)
        by 0x5193D1B: init (main.cpp:36)
        by 0x805DC87: main (main.cpp:104)
    il semble donc que le programme plante sur la chaîne "spv-numeroteur" ?!?
    Que nenni, me disant que j'ai fait déborder la pile, je fais de braves new pour toutes mes variables, mais rien n'y fait.
    Que nenni, je stocke cette chaîne dans une variable qui a été allouée auparavent, mais le programme plante alors plus loin sur le prochain appel du type :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    mafonction("une chaine statique");
    fonction dans laquelle il y a une conversion de char * vers une string.


    Sniff, quelqu'un aurait-il une idée ?

    P.S.:
    libairies : STL, Boost, dl
    plateforme : linux 2.6.17
    glibc : 2.6-2

    P.P.S :
    si je n'ai pas posté dans le bon forum, n'hésitez pas à le signalez (j'ai un peu hésiter :-p)

  2. #2
    Expert confirmé
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Décembre 2003
    Messages
    3 549
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Décembre 2003
    Messages : 3 549
    Par défaut
    Est-ce que tu peux faire un testcase ?
    Un exemple minimal réduit qui compile et qui démontre le problème.

  3. #3
    Membre éprouvé
    Profil pro
    Inscrit en
    Juin 2006
    Messages
    107
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2006
    Messages : 107
    Par défaut j'ai avancé
    Bon, je suppose que cela ne vient pas de string (c'était un peu évident :-P), mais plutôt de ma gestion de la librairie mémoire . Je vais poster dans une autre section (laquelle ?), mais voici à tout hasard un Snipped Code tout simple :

    le code de la dll :
    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
    #include <iostream>
    using namespace std;
    //#include "isicom_utils.hpp"
     
    #define ushort unsigned short int
    #ifdef WINDOWS
    #define MY_EXPORT __declspec(dllexport)
    #else
    #define MY_EXPORT
    #endif
     
     
    struct s_datas{
      string toto;
    };
     
    static struct s_datas *datas = NULL;
     
    extern "C"
    {
      MY_EXPORT bool init(void)
      {
        datas = new struct s_datas ();
        char *buffer = (char*)malloc(100*sizeof(char));
        strcpy(buffer, "initializing");
        datas->toto = buffer;
        //free(buffer);
        return true;
      }
     
    }
    le code du programme principal :
    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
     
    #include <iostream>
    #include <dlfcn.h>
    using namespace std;
     
    #include <boost/thread/thread.hpp>
     
     
    struct s_datas{
       boost::thread_group thread;
    };
    int main(int argc, char *argv[])
     {
       bool ok;
       int i ;
       string tempString;
       struct s_datas *datas = NULL;
       datas = new struct s_datas ();
     
       void *hndl= dlopen("libspv-numeroteur.so", RTLD_LAZY);
       v oid *func = dlsym(hndl, "init");
       typedef bool (*Toto)(void);
       ok = ((Toto)func)();
     
       return 0;
    }
    et bien avec ce petit code, j'obtiens des monstruosités lorsque je passe valgrind (extrait):
    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
    ==28524== Invalid write of size 4
    ==28524==    at 0x4188BB2: boost::thread_group::thread_group() (in /usr/lib/libboost_thread-gcc41-mt-1_34_1.so.1.34.1)
    ==28524==    by 0x8048C00: s_datas::s_datas() (main.cpp:29)
    ==28524==    by 0x4028992: init (main.cpp:29)
    ==28524==    by 0x8048B8B: main (main.cpp:45)
    [...]
    ==28524== Invalid write of size 4
    ==28524==    at 0x4415263: pthread_mutex_init (in /lib/i686/cmov/libpthread-2.6.so)
    ==28524==    by 0x439C9CC: pthread_mutex_init (in /lib/i686/cmov/libc-2.6.so)
    ==28524==    by 0x418742C: boost::mutex::mutex() (in /usr/lib/libboost_thread-gcc41-mt-1_34_1.so.1.34.1)
    ==28524==    by 0x4188BBC: boost::thread_group::thread_group() (in /usr/lib/libboost_thread-gcc41-mt-1_34_1.so.1.34.1)
    ==28524==    by 0x8048C00: s_datas::s_datas() (main.cpp:29)
    ==28524==    by 0x4028992: init (main.cpp:29)
    ==28524==    by 0x8048B8B: main (main.cpp:45)
    ==28524==  Address 0x505D734 is not stack'd, malloc'd or (recently) free'd
    et ca n'en finit pas.

    sniff.

  4. #4
    Membre éprouvé
    Profil pro
    Inscrit en
    Juin 2006
    Messages
    107
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2006
    Messages : 107
    Par défaut Mouaip mouaip je progresse
    avec aussi peu de code, quelque chose m'a sauté aux yeux :

    j'ai défini deux structures (une dans la lib, l'autre dans le programme principal) qui porte le même nom (à priori pas gênant, non ?).
    Et bien en renommant l'une des deux structures j'ai plus d'alerte de valgrind !
    Je n'ai pas le temps (je ferais cela ce week end) de modifier l'appli original pour voir ce que cela donne (je dois absolument avancer et je peux le faire avec un petit bout de code déjà fait).

    Mais je pense que c'est une bonne piste !

    Quelqu'un a une idée du sous-forum dans lequel je dois poster pour ce genre de problème ?

  5. #5
    Membre éprouvé
    Profil pro
    Inscrit en
    Juin 2006
    Messages
    107
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2006
    Messages : 107
    Par défaut C'est fini
    Tous mes problèmes sont enfin réglés !

    Alors, pour les rares qui me lisent :-), mes problèmes avaient deux causes (assez subtiles en fait) :
    - l'histoire du struct plus haut (si quelqu'un pouvait m'expliquer le pourquoi, ce serait gentil)
    - le chargement de la dll :
    toutes mes données sont générées (dll, binaire, etc) dans toto/bin, et par facilité je lançais mon exécutable de la manière suivante : bin/monexe (et oui je suis dans toto). Normalement, cela doit échouer (ne sachant pas où sont les dll le chargement doit s'arrêter) or inexplicablement (je t'attends lecteur) le chargement s'effectuait (du moins tous les appels réussissaient et je parvenais à lancer les fonctions embarquées dans les dll) ! mais cela générait des erreurs ultérieurement.

    P.S. :
    aux admins, peut-être faudrait-il déplacer ce fil dans une section plus adapté ?

    aux lecteurs, pensez pas que ce serait bien de mettre ces problèmes dans la FAQ ?

  6. #6
    Expert confirmé

    Homme Profil pro
    Ingénieur systèmes et réseaux
    Inscrit en
    Février 2007
    Messages
    4 253
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur systèmes et réseaux
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Février 2007
    Messages : 4 253
    Billets dans le blog
    3
    Par défaut
    Si la dll est a coté de l'exe, c'est normal que ca marche... c'est d'ailleurs le comportement "standard" (et le premier endroit ou windows va chercher les DLLs).
    On a bien dit le répertoire de l'application ! Pas celui "courant"... que tu sois sur Z:\JJHSD\zerui pour lancer C:\program files (x86)\moi\monprog\monprog.exe ne change rien...

  7. #7
    Membre averti
    Profil pro
    Inscrit en
    Juillet 2007
    Messages
    21
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2007
    Messages : 21
    Par défaut
    outes mes données sont générées (dll, binaire, etc) dans toto/bin, et par facilité je lançais mon exécutable de la manière suivante : bin/monexe (et oui je suis dans toto). Normalement, cela doit échouer (ne sachant pas où sont les dll le chargement doit s'arrêter) or inexplicablement (je t'attends lecteur) le chargement s'effectuait (du moins tous les appels réussissaient et je parvenais à lancer les fonctions embarquées dans les dll) ! mais cela générait des erreurs ultérieurement.
    Et ce problème tu l'as résolu simplement en te mettant dans le répertoire bin comme répertoire courant ???
    Parce que j'ai les même problèmes que toi, et j'avais en effet une classe du même nom que celle d'une dll (mais que je n'avais pas importée pourtant ? peut être la .a qui posait problème...) et même si je renomme cette classe j'ai toujours des sigsegv sur les std::string::c_str()....
    (Et je sais que cela vient du passage en dll car en tant que librairie statique tout marche nickel et sans la classe avec le même nom )

  8. #8
    Membre éprouvé
    Profil pro
    Inscrit en
    Juin 2006
    Messages
    107
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2006
    Messages : 107
    Par défaut
    • nicroman
      Si la dll est a coté de l'exe, c'est normal que ca marche...
      Mouaip peut être ; mais je développe sous linux, les différentes doc ne le disent pas (http://man.he.net/man3/dlopen), et l'expérience me dit le contraire.
      M'enfin.
    • lovecpp
      essaies toi aussi de faire un SnippedCode, je pourrais peut être t'aider. Toujours est-il que mes problèmes ont disparus en faisant comme indiqué plus haut.
      Prends bien la peine de vérifier que tu charges bien le symbole que tu veux (en m'en mêlant avec les pointeurs des différents fonctions, je parvenais à lancer la bonne fonction -init dans mon cas- alors que le pointeur contenait l'adresse d'une autre fonction -start-, et en ayant plus loin un segfault).
      Fais bien attention à ne pas avoir de variables globales ayant le même nom dans tes différentes dll (met un static devant ces variables).

      J'ai l'impression que quand il y a une crasse faite en mémoire et avec des thread boost, il faut s'attendre à n'importe quoi comme problèmes.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 2
    Dernier message: 23/10/2007, 09h54
  2. Questions sur les std::string
    Par olive_le_malin dans le forum SL & STL
    Réponses: 6
    Dernier message: 23/02/2007, 08h44
  3. [stl] questions sur la classe string
    Par r0d dans le forum SL & STL
    Réponses: 3
    Dernier message: 23/02/2007, 00h31
  4. Question sur le type String
    Par bugland dans le forum Langage
    Réponses: 9
    Dernier message: 12/02/2007, 13h47
  5. Question facile sur la classe string
    Par MarOne dans le forum Langage
    Réponses: 9
    Dernier message: 20/04/2006, 14h28

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