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 :

Malloc => segFault


Sujet :

C++

  1. #1
    Membre confirmé
    Profil pro
    Inscrit en
    Février 2006
    Messages
    63
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations forums :
    Inscription : Février 2006
    Messages : 63
    Par défaut Malloc => segFault
    Bonjour,

    J'ai écrit un programme (calculant des indices de sensibilité pour mon stage de 2A) qui nécessite d'initialiser tout plein de zones mémoire (pour aller plus vite):

    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
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
     
     
    int i,ip,ipp;
    long j,k,l,aux,tmpl;
    long *casesY,*p,*estimationsX,*estimationsY;
    long **casesX,**estimationsXX,**estimationsXY=0;
    long ***estimationsXXY;
     
    double sum,H0=0,pasX,tmp;
    double *infX,*infY,*supX,*supY,*pasY,*mS1=0,*minS1=0,*maxS1=0,*sigS1=0;
    double **mS2=0,**minS2=0,**maxS2=0,**sigS2=0,**X,**Y,**HK=0;
    double ***HK2=0;
     
    /* initialisation des tableaux contenant les indices */
    if (Si) {
        HK=(double**)malloc(dim_x*sizeof(double*));
        for (i=dim_x-1; i>=0; i--) {
            HK[i]=(double*)malloc(R*sizeof(double));
            for (ip=R-1; ip>=0; ip--) HK[i][ip]=0;
        }
        mS1=(double*)malloc(dim_x*sizeof(double));
        minS1=(double*)malloc(dim_x*sizeof(double));
        maxS1=(double*)malloc(dim_x*sizeof(double));
        sigS1=(double*)malloc(dim_x*sizeof(double));
    } 
    if (Sij) {
        HK2=(double***)malloc(dim_x*sizeof(double**));
        for (i=dim_x-1; i>=0; i--) {
            HK2[i]=(double**)malloc(dim_x*sizeof(double*));
            for (ip=dim_x-1; ip>=0; ip--) {
                HK2[i][ip]=(double*)malloc(R*sizeof(double));
                for (ipp=R-1; ipp>=0; ipp--) HK2[i][ip][ipp]=0;
            }
        }
        mS2=(double**)malloc(dim_x*sizeof(double*));
        for (i=dim_x-1; i>=0; i--) mS2[i]=(double*)malloc(dim_x*sizeof(double));
        minS2=(double**)malloc(dim_x*sizeof(double*));
        for (i=dim_x-1; i>=0; i--) minS2[i]=(double*)malloc(dim_x*sizeof(double));
        maxS2=(double**)malloc(dim_x*sizeof(double*));
        for (i=dim_x-1; i>=0; i--) maxS2[i]=(double*)malloc(dim_x*sizeof(double));
        sigS2=(double**)malloc(dim_x*sizeof(double*));
        for (i=dim_x-1; i>=0; i--) sigS2[i]=(double*)malloc(dim_x*sizeof(double));
    } 
     
    /* autres initialisations */
    aux=puiss(n+1,dim_y); 
    p=(long*)malloc(dim_y*sizeof(long));
    for (i=dim_y; i>=0; i--) p[i]=puiss(n+1,i);
    estimationsY=(long*)malloc((aux+1)*sizeof(long)); 
    X=(double**)malloc(dim_x*sizeof(double*));
    for (i=dim_x-1; i>=0; i--) X[i]=(double*)malloc(S*sizeof(double)); 
    infX=(double*)malloc(dim_x*sizeof(double));
    supX=(double*)malloc(dim_x*sizeof(double));
    infY=(double*)malloc(dim_y*sizeof(double));
    supY=(double*)malloc(dim_y*sizeof(double));
    pasY=(double*)malloc(dim_y*sizeof(double));
    casesY=(long*)malloc(S*sizeof(long));
    casesX=(long**)malloc(dim_x*sizeof(long*));
    for (i=dim_x-1; i>=0; i--) casesX[i]=(long*)malloc(S*sizeof(long));
    estimationsX=(long*)malloc((n+1)*sizeof(long));
    if (Si) {
       estimationsXY=(long**)malloc((n+1)*sizeof(long*));
       for (j=n; j>=0; j--)
           estimationsXY[j]=(long*)malloc((aux+1)*sizeof(long));
    }
    estimationsXX=(long**)malloc((n+1)*sizeof(long*));
    estimationsXXY=(long***)malloc((n+1)*sizeof(long**));
    for (j=n; j>=0; j--) {
        estimationsXX[j]=(long*)malloc((n+1)*sizeof(long));
        estimationsXXY[j]=(long**)malloc((n+1)*sizeof(long*));
        for (k=n; k>=0; k--) 
            estimationsXXY[j][k]=(long*)malloc((aux+1)*sizeof(long));
    }
    Contrairement aux apparences c'est bien du C++ ^^
    En revanche:

    - Ca marche avec dev-cpp sous windows
    - Ca plante systématiquement avant la fin des allocations avec g++ sous Unix; message d'erreur:

    (gdb) run e Parametres/paramE_hs.dat hs 1000 100
    Starting program: /home/iooss/benjamin/main e Parametres/paramE_hs.dat hs 1000 100

    Program received signal SIGSEGV, Segmentation fault.
    0x42074675 in _int_malloc () from /lib/tls/libc.so.6
    (gdb) bt
    #0 0x42074675 in _int_malloc () from /lib/tls/libc.so.6
    #1 0x4207378d in malloc () from /lib/tls/libc.so.6
    #2 0x0804ebcb in entrop ()
    #3 0x0804adff in main ()
    #4 0x42015704 in __libc_start_main () from /lib/tls/libc.so.6

    Faut-il que je transforme tous mes "malloc" en "new" ?
    Ce qui m'embête c'est que le code suivant fonctionne sous Unix avec g++:

    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
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
     
     
    int i,ip,ipp,j;
    long k;
    double V0=0,my=0;
    double *Y,*Yp,*mS1=0,*mSt=0,*minS1=0,*minSt=0,*maxS1=0,*maxSt=0,*sigS1=0,*sigSt=0;
    double **mS2=0,**minS2=0,**maxS2=0,**sigS2=0,**X1,**X2,**sav,**S1=0,**St=0;
    double ***S2=0;
     
    /* initialisation des tableaux contenant les indices */
    if (Si) {
        S1=(double**)malloc(dim_x*sizeof(double*));
        for (i=dim_x-1; i>=0; i--) {
            S1[i]=(double*)malloc(R*sizeof(double)); 
            for (ip=R-1; ip>=0; ip--) S1[i][ip]=0;
        }
        mS1=(double*)malloc(dim_x*sizeof(double));
        minS1=(double*)malloc(dim_x*sizeof(double));
        maxS1=(double*)malloc(dim_x*sizeof(double));
        sigS1=(double*)malloc(dim_x*sizeof(double));
    }
    if (Sij) {
        S2=(double***)malloc(dim_x*sizeof(double**));
        for (i=dim_x-1; i>=0; i--) {
            S2[i]=(double**)malloc(dim_x*sizeof(double*));
            for (ip=dim_x-1; ip>=0; ip--) {
                S2[i][ip]=(double*)malloc(R*sizeof(double));
                for (ipp=R-1; ipp>=0; ipp--) S2[i][ip][ipp]=0;
            }
        }
        mS2=(double**)malloc(dim_x*sizeof(double*));
        for (i=dim_x-1; i>=0; i--) mS2[i]=(double*)malloc(dim_x*sizeof(double));
        minS2=(double**)malloc(dim_x*sizeof(double*));
        for (i=dim_x-1; i>=0; i--) minS2[i]=(double*)malloc(dim_x*sizeof(double));
        maxS2=(double**)malloc(dim_x*sizeof(double*));
        for (i=dim_x-1; i>=0; i--) maxS2[i]=(double*)malloc(dim_x*sizeof(double));
        sigS2=(double**)malloc(dim_x*sizeof(double*));
        for (i=dim_x-1; i>=0; i--) sigS2[i]=(double*)malloc(dim_x*sizeof(double));
    } 
    if (Sti) {
        St=(double**)malloc(dim_x*sizeof(double*));
        for (i=dim_x-1; i>=0; i--) {
            St[i]=(double*)malloc(R*sizeof(double));
            for (ip=R-1; ip>=0; ip--) St[i][ip]=0;
        }
        mSt=(double*)malloc(dim_x*sizeof(double));
        minSt=(double*)malloc(dim_x*sizeof(double));
        maxSt=(double*)malloc(dim_x*sizeof(double));
        sigSt=(double*)malloc(dim_x*sizeof(double));
    }
     
    /* autres initialisations */
    X1=(double**)malloc(dim_x*sizeof(double*));
    for (i=dim_x-1; i>=0; i--) X1[i]=(double*)malloc(S*sizeof(double));
    X2=(double**)malloc(dim_x*sizeof(double*));
    for (i=dim_x-1; i>=0; i--) X2[i]=(double*)malloc(S*sizeof(double));
    sav=(double**)malloc(dim_x*sizeof(double*));
    for (i=dim_x-1; i>=0; i--) sav[i]=(double*)malloc(S*sizeof(double));
    alors que les allocations nécessaires sont plus grandes que dans le cas précédent (n de l'ordre de 100, S peut atteindre 500000, 1000000..etc).

    Je n'y comprend rien (comme d'habitude :-/)

    Merci d'avance,
    Benjamin.

  2. #2
    Membre chevronné
    Profil pro
    Inscrit en
    Juin 2005
    Messages
    464
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2005
    Messages : 464
    Par défaut
    ton code n'est pas sécurisé du tout: tu écris dans des zones mémoires pour lesquelles le succès d'allocation n'a pas été vérifié.

    pas étonnant dans ces conditions qu'il y ait des crashes plus ou moins aléatoires...

  3. #3
    Invité
    Invité(e)
    Par défaut
    je ne me suis pas penché sur le code plus que ca.
    j'ai une question pourtant :

    si c'est bel et bien du C++, pourquoi ne pas utiliser new pour allouer ta mémoire ?
    et puisque tu as l'air de gérer plusieurs tableaux, pourquoi ne pas se servir dans les conteneurs STL ?? (std::vector par ex)

  4. #4
    Membre chevronné
    Profil pro
    Inscrit en
    Juin 2005
    Messages
    464
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2005
    Messages : 464
    Par défaut
    Citation Envoyé par toxcct
    si c'est bel et bien du C++, pourquoi ne pas utiliser new pour allouer ta mémoire ?
    Si je peux me permettre, ça ne changerait rien : new, au même titre que malloc peut échouer. D'ailleurs la plupart des implémentations de new utilisent malloc pour allouer la mémoire des objets instanciés...

  5. #5
    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
    Et pire, le new standard lance une exception en cas d'échec. Dans le cas d'une allocation de masse, c'est pas le mieux...

    En tout cas, pour plus de sécurité, je pense que tu peux réduire le nombre d'allocations à une par dimension pour chaque tableau, ce qui serait peut-être un peu moins fouillis (et réclamerait moins de tests de réussite ou échec).
    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.

  6. #6
    Membre confirmé
    Profil pro
    Inscrit en
    Février 2006
    Messages
    63
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations forums :
    Inscription : Février 2006
    Messages : 63
    Par défaut
    Les conteneurs de la STL sont beaucoup trop lents ;o) (en tout cas c'est ce que j'ai constaté en programmant un jeu de dame cette année).

    Ca m'inquiète quand même que ces allocations échouent: même pour S=10 et n=10 ça plante, alors que dans ce cas il faut juste quelques centaines d'octets, au pire quelques milliers :-/

    Je suis d'accord que le code n'est pas sécurisé du tout, mais si on refuse de m'allouer 100 octets parce qu'il n'y a plus de mémoire, hein..

  7. #7
    Membre confirmé
    Profil pro
    Inscrit en
    Février 2006
    Messages
    63
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations forums :
    Inscription : Février 2006
    Messages : 63
    Par défaut
    Citation Envoyé par Médinoc
    En tout cas, pour plus de sécurité, je pense que tu peux réduire le nombre d'allocations à une par dimension pour chaque tableau, ce qui serait peut-être un peu moins fouillis (et réclamerait moins de tests de réussite ou échec).
    Bonne idée, je vais essayer ^^

  8. #8
    Membre expérimenté
    Avatar de superspag
    Profil pro
    Inscrit en
    Janvier 2006
    Messages
    153
    Détails du profil
    Informations personnelles :
    Âge : 45
    Localisation : France, Isère (Rhône Alpes)

    Informations forums :
    Inscription : Janvier 2006
    Messages : 153
    Par défaut
    Les conteneurs de la STL sont beaucoup trop lents ;o) (en tout cas c'est ce que j'ai constaté en programmant un jeu de dame cette année).
    C'est surtout vraie en Debug mais en Release il n'y a pas de difference ou trés peu... Le plus dur je pense, c'est de bien choisir son conteneur. Selon l'utilisation, certains conteneurs sont préférables à d'autres...

  9. #9
    Expert confirmé
    Avatar de Luc Hermitte
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2003
    Messages
    5 292
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Août 2003
    Messages : 5 292
    Par défaut
    Ce n'est pas parce qu'un code semble fonctionner qu'il est correct. Il est vite fait de faire des buffers overflow. Quand on commence à avoir des **, c'est une de trop -- si ce n'est pas deux. Alors ***, c'est des bugs à coup sûr.

    Citation Envoyé par Médinoc
    Et pire, le new standard lance une exception en cas d'échec. Dans le cas d'une allocation de masse, c'est pas le mieux...
    Au moins inutile de mettre 150 if pour tester tous les echecs possibles. Une exception, et on avorte. Après, la récupération de la mémoire n'est pas plus compliquée (ni plus simple). Inutile aussi de spécifier des choses que le compilo connait déjà => les tailles des types primitifs à alouer.

    En tout cas, pour plus de sécurité, je pense que tu peux réduire le nombre d'allocations à une par dimension pour chaque tableau, ce qui serait peut-être un peu moins fouillis (et réclamerait moins de tests de réussite ou échec).
    Ou utiliser directement un truc efficace qui est fait pour gérer plusieurs dimensions => boost.multi_array, std::vector<std::vector<...>>.

    Les conteneurs de la STL sont beaucoup trop lents ;o) (en tout cas c'est ce que j'ai constaté en programmant un jeu de dame cette année).
    C'est sûr que si tu les copies à chaque passage de paramètres ...
    google => "n1666 filtetype:pdf"
    Blog|FAQ C++|FAQ fclc++|FAQ Comeau|FAQ C++lite|FAQ BS|Bons livres sur le C++
    Les MP ne sont pas une hotline. Je ne réponds à aucune question technique par le biais de ce média. Et de toutes façons, ma BAL sur dvpz est pleine...

  10. #10
    Membre confirmé
    Profil pro
    Inscrit en
    Février 2006
    Messages
    63
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations forums :
    Inscription : Février 2006
    Messages : 63
    Par défaut
    Citation Envoyé par Luc Hermitte
    C'est sûr que si tu les copies à chaque passage de paramètres ...
    google => "n1666 filtetype:pdf"
    Non non j'avais fait attention à ça, mais dans le cas du prog jeu de dames je devais représenter des coups par des suites de coordonnées; au lieu de faire des push_back sur un vecteur ça a gagné pas mal de temps d'utiliser un simple pointeur initialisé avec une taille assez grande.

    Merci à tout le monde, je devrais m'en sortir avec tous ces conseils ^^

  11. #11
    Membre expérimenté
    Avatar de superspag
    Profil pro
    Inscrit en
    Janvier 2006
    Messages
    153
    Détails du profil
    Informations personnelles :
    Âge : 45
    Localisation : France, Isère (Rhône Alpes)

    Informations forums :
    Inscription : Janvier 2006
    Messages : 153
    Par défaut
    au lieu de faire des push_back sur un vecteur ça a gagné pas mal de temps d'utiliser un simple pointeur initialisé avec une taille assez grande
    Il faut faire attention aux push_back qui peuvent provoquer une réallocation de tout le vector !
    Le vector doit connaitre sa capacité max pour etre otpimal.
    Tu peux utiliser la fonction setCapacity et ainsi utiliser des push_back tranquillement jusqu'a la taille max. Sinon il faut allouer le vector directement à la taille souhaité et y acceder via l'operateur [].

    Exemple d'allocation d'une matrice de taille N :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    const unsigned short N = 3000;
    std::vector< std::vector<double> > mat(N, std::vector<double>(N)); // Allocation d'une matrice NxN

  12. #12
    Expert confirmé
    Avatar de Luc Hermitte
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2003
    Messages
    5 292
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Août 2003
    Messages : 5 292
    Par défaut
    - std::vector<>::reserve() augmente la capacité ; il n'y a aucune construction/initialisation
    - std::vector<>::resize() augmente la taille "officielle" (peut faire un appel à réserve si la capacité est insuffisante), et construit les nouveaux éléments à une valeur par défaut pouvant être explicitée
    - Le constructor prenant une taille en paramètre réalise un appel à resize (dans le principe)
    Blog|FAQ C++|FAQ fclc++|FAQ Comeau|FAQ C++lite|FAQ BS|Bons livres sur le C++
    Les MP ne sont pas une hotline. Je ne réponds à aucune question technique par le biais de ce média. Et de toutes façons, ma BAL sur dvpz est pleine...

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

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. Segfault étrange sur un malloc
    Par |PaRa-BoL dans le forum C
    Réponses: 38
    Dernier message: 17/01/2007, 14h57
  3. Pb : malloc qui marche une fois sur deux .... ?
    Par guillaume_pfr dans le forum C
    Réponses: 14
    Dernier message: 21/07/2003, 09h52
  4. Erreur de sgmentation avec malloc
    Par simonm dans le forum C
    Réponses: 5
    Dernier message: 27/02/2003, 08h29
  5. Réponses: 4
    Dernier message: 03/12/2002, 16h47

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