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 :

Segment Fault - Sous windows


Sujet :

C

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé
    Homme Profil pro
    Lycéen
    Inscrit en
    Mars 2014
    Messages
    76
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 59
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Lycéen

    Informations forums :
    Inscription : Mars 2014
    Messages : 76
    Par défaut Segment Fault - Sous windows
    Bonjour,

    je développe actuellement une application en C sous Linux, et je n'ai aucun soucis à son lancement.. Je décide de tester sous Windows, et j'ai l'agréable surprise d'avoir un jolie Segment Fault à son lancement..
    Après quelques recherches mon problème vient de mes variables.. Je déclare beaucoup de tableaux tridimensionnels et j'ai l'impression que Windows refuse de m'accorder l'espace mémoire nécessaire.


    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
     
             int nfloor = 7, nroommax = 52;
             int local[nroommax+1][nfloor+1], numero[nroommax+1][nfloor+1], nwindow[nroommax+1][nfloor+1], nwindow_open[nroommax+1][nfloor+1], nlh[nroommax+1][nfloor+1], 
    	      nlvh[nroommax+1][nfloor+1], nlvb[nroommax+1][nfloor+1], nlv_bas[nroommax+1][nfloor+1];
     
    	int adjacent_hor[nroommax+1][nfloor+1][nroommax+1], adjacent_verh[nroommax+1][nfloor+1][nroommax+1], adjacent_verb[nroommax+1][nfloor+1][nroommax+1],
    	    adjacent_ver_bas[nroommax+1][nfloor+1][nroommax+1], door[nroommax+1][nfloor+1][nroommax+1], door_open[nroommax+1][nfloor+1][nroommax+1],
    	    nombre_parois[nroommax+1][nfloor+1];
     
    	double alpha[nroommax+1][nfloor+1], wo[nroommax+1][nfloor+1], wf[nroommax+1][nfloor+1], awf[nroommax+1][nfloor+1], af[nroommax+1][nfloor+1],
                     dhc[nroommax+1][nfloor+1], tam[nroommax+1][nfloor+1], hrr[nroommax+1][nfloor+1], hrrcr[nroommax+1][nfloor+1], pig[nroommax+1][nfloor+1],
                     tif[nroommax+1][nfloor+1], pfd[nroommax+1][nfloor+1], p[nroommax+1][nfloor+1], tfo[nroommax+1][nfloor+1], larg_local[nroommax+1][nfloor+1],
    	         facteur_ventilation[nroommax+1][nfloor+1], long_local[nroommax+1][nfloor+1], haut_local[nroommax+1][nfloor+1], phi[nroommax+1][nfloor+1],
    	         taux_fo[nroommax+1][nfloor+1], q[nroommax+1][nfloor+1], ho_local[nroommax+1][nfloor+1], taux_max_gr[nroommax+1][nfloor+1], taux_fd[nroommax+1][nfloor+1],
    	         surface_totale[nroommax+1][nfloor+1], hauteur_flamme[nroommax+1][nfloor+1], facteur_paroi[nroommax+1][nfloor+1], /*surface_paroi_v[nroommax+1][nfloor+1],*/
    	         critere[nroommax+1][nfloor+1], /*sigma_alpha[nroommax+1][nfloor+1],*/ tamb[nroommax+1][nfloor+1], tig[nroommax+1][nfloor+1], distance_ouverture_ver[nroommax +1][nfloor+1];
     
    	double ao[nroommax+1][nfloor+1][6+1], ho[nroommax+1][nfloor+1][6+1], pbf_h[nroommax+1][nroommax+1][nfloor+1], pbf_vh[nroommax+1][nroommax+1][nfloor+1], pbf_vb[nroommax+1][nroommax+1][nfloor+1],
                     surface_paroi[nroommax+1][nfloor+1][6+1], rokocp[nroommax+1][nfloor+1][6+1], mu_frr_door[nroommax+1][nfloor+1][nroommax+1], sigma_frr_door[nroommax+1][nfloor+1][nroommax+1],
    	         mu_frr_h[nroommax+1][nfloor+1][nroommax+1], sigma_frr_h[nroommax+1][nfloor+1][nroommax+1];
     
            double sigma_frr_vb[nroommax+1][nfloor+1][nroommax+1], mu_frr_vh[nroommax+1][nfloor+1][nroommax+1], sigma_frr_vh[nroommax+1][nfloor+1][nroommax+1], mu_frr_vb[nroommax+1][nfloor+1][nroommax+1];
     
    	bool paroi_hor[nroommax+1][nfloor+1][nroommax+1], paroi_vh[nroommax+1][nfloor+1][nroommax+1], paroi_vb[nroommax+1][nfloor+1][nroommax+1];
    Si je mets en commentaire une partie des tableaux le programme ne fait plus de segment fault..
    Ce que je trouve bizarre c'est que le pc ou il y a Linux et ou sa fonctionne est mois puissant que celui ou y a windows.. Les deux sont en 64 bits...

    Si quelqu'un aurait une idée pour régler ce soucis, je suis preneur, merci !

  2. #2
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Chercheur d'emploi
    Inscrit en
    Septembre 2007
    Messages
    7 485
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Chercheur d'emploi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2007
    Messages : 7 485
    Par défaut
    Bonjour,

    Citation Envoyé par Reverse_ Voir le message
    je développe actuellement une application en C sous Linux, et je n'ai aucun soucis à son lancement.. Je décide de tester sous Windows, et j'ai l'agréable surprise d'avoir un jolie Segment Fault à son lancement..
    Après quelques recherches mon problème vient de mes variables.. Je déclare beaucoup de tableaux tridimensionnels et j'ai l'impression que Windows refuse de m'accorder l'espace mémoire nécessaire.

    Si je mets en commentaire une partie des tableaux le programme ne fait plus de segment fault..
    Ce que je trouve bizarre c'est que le pc ou il y a Linux et ou sa fonctionne est mois puissant que celui ou y a windows.. Les deux sont en 64 bits...
    C'est dû au fait que ton programme doit être naturellement bugué et qu'il a une chance sur deux de planter, en fonction de l'environnement. C'est assez courant quand on débute en C. Il arrive même parfois que selon la plateforme, le programme plante avant ou APRÈS avoir rempli son travail. Dans le dernier cas, il arrive que le programme reste en production des années avant que l'on s'en rende compte.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
             int nfloor = 7, nroommax = 52;
             int local[nroommax+1][nfloor+1], numero[nroommax+1][nfloor+1], nwindow[nroommax+1][nfloor+1], nwindow_open[nroommax+1][nfloor+1], nlh[nroommax+1][nfloor+1], 
    	      nlvh[nroommax+1][nfloor+1], nlvb[nroommax+1][nfloor+1], nlv_bas[nroommax+1][nfloor+1];
    Contrairement à ce que l'on pourrait penser, déclarer les choses de cette façon est une mauvaise pratique. D'abord parce que tous tes tableaux sont déclarés dans la pile, dont il faut faire un usage le plus sobre possible. Si tu as besoin de plages de données vastes et/ou persistantes, il vaut mieux explicitement demander de la place au système avec malloc().

    Ensuite, il vaut mieux également déclarer tes dimensions nfloor et nroommax soit avec des #define, soit au moins avec des constantes car dans le cas présent, tu déclares des variables qui ont une existence propre et qui peuvent être modifiés mais surtout, cela oblige le compilateur à réserver l'espace de tes tableaux au runtime, en utilisant les VLA, disponibles depuis C99.

    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
    	int adjacent_hor[nroommax+1][nfloor+1][nroommax+1], adjacent_verh[nroommax+1][nfloor+1][nroommax+1], adjacent_verb[nroommax+1][nfloor+1][nroommax+1],
    	    adjacent_ver_bas[nroommax+1][nfloor+1][nroommax+1], door[nroommax+1][nfloor+1][nroommax+1], door_open[nroommax+1][nfloor+1][nroommax+1],
    	    nombre_parois[nroommax+1][nfloor+1];
     
    	double alpha[nroommax+1][nfloor+1], wo[nroommax+1][nfloor+1], wf[nroommax+1][nfloor+1], awf[nroommax+1][nfloor+1], af[nroommax+1][nfloor+1],
                     dhc[nroommax+1][nfloor+1], tam[nroommax+1][nfloor+1], hrr[nroommax+1][nfloor+1], hrrcr[nroommax+1][nfloor+1], pig[nroommax+1][nfloor+1],
                     tif[nroommax+1][nfloor+1], pfd[nroommax+1][nfloor+1], p[nroommax+1][nfloor+1], tfo[nroommax+1][nfloor+1], larg_local[nroommax+1][nfloor+1],
    	         facteur_ventilation[nroommax+1][nfloor+1], long_local[nroommax+1][nfloor+1], haut_local[nroommax+1][nfloor+1], phi[nroommax+1][nfloor+1],
    	         taux_fo[nroommax+1][nfloor+1], q[nroommax+1][nfloor+1], ho_local[nroommax+1][nfloor+1], taux_max_gr[nroommax+1][nfloor+1], taux_fd[nroommax+1][nfloor+1],
    	         surface_totale[nroommax+1][nfloor+1], hauteur_flamme[nroommax+1][nfloor+1], facteur_paroi[nroommax+1][nfloor+1], /*surface_paroi_v[nroommax+1][nfloor+1],*/
    	         critere[nroommax+1][nfloor+1], /*sigma_alpha[nroommax+1][nfloor+1],*/ tamb[nroommax+1][nfloor+1], tig[nroommax+1][nfloor+1], distance_ouverture_ver[nroommax +1][nfloor+1];
     
    	double ao[nroommax+1][nfloor+1][6+1], ho[nroommax+1][nfloor+1][6+1], pbf_h[nroommax+1][nroommax+1][nfloor+1], pbf_vh[nroommax+1][nroommax+1][nfloor+1], pbf_vb[nroommax+1][nroommax+1][nfloor+1],
                     surface_paroi[nroommax+1][nfloor+1][6+1], rokocp[nroommax+1][nfloor+1][6+1], mu_frr_door[nroommax+1][nfloor+1][nroommax+1], sigma_frr_door[nroommax+1][nfloor+1][nroommax+1],
    	         mu_frr_h[nroommax+1][nfloor+1][nroommax+1], sigma_frr_h[nroommax+1][nfloor+1][nroommax+1];
     
            double sigma_frr_vb[nroommax+1][nfloor+1][nroommax+1], mu_frr_vh[nroommax+1][nfloor+1][nroommax+1], sigma_frr_vh[nroommax+1][nfloor+1][nroommax+1], mu_frr_vb[nroommax+1][nfloor+1][nroommax+1];
     
    	bool paroi_hor[nroommax+1][nfloor+1][nroommax+1], paroi_vh[nroommax+1][nfloor+1][nroommax+1], paroi_vb[nroommax+1][nfloor+1][nroommax+1];
    Il faut absolument garder à l'esprit que la déclaration d'une variable ou d'un tableau n'est pas qu'une simple annonce formelle comme on le ferait en mathématiques (où l'on peut éventuellement travailler avec l'infini) mais que ton compilateur va physiquement réserver dès le départ pour ton usage l'espace total que le tableau peut adresser ! Avec ça, tu déclares des centaines de tableaux et pour chacun d'eux, tu déclares plusieurs dimensions, ce qui fait exploser leur taille de façon exponentielle.

    Le code ci-dessus réserve pas moins de 2799672 octets, soit 2,67 Mio dans la pile, là où l'usage prescrit de ne pas utiliser plus de quelques kilo-octets en permanence. Elle n'est pas faite pour.

    Par ailleurs, il faut aussi se souvenir que la pile ne sert pas qu'à allouer de la place pour les variables locales : elle sert aussi et surtout à stocker les informations relatives aux différents appels en cascade aux différentes fonctions, non seulement de ton propre programme, mais aussi à celles des bibliothèques que tu utilises. Spécialement dans le cas d'utilisation de fonctions récursives. Et il n'est pas possible de savoir à l'avance et dans tous les cas si une fonction récursive va forcément se terminer, ni de quel espace elle aura besoin au total. La pile est donc un espace raisonnablement défini en fonction de l'usage constaté le plus couramment, et qui peut-être dépassée si elle a été sous-dimensionnée.

  3. #3
    Membre confirmé
    Homme Profil pro
    Lycéen
    Inscrit en
    Mars 2014
    Messages
    76
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 59
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Lycéen

    Informations forums :
    Inscription : Mars 2014
    Messages : 76
    Par défaut
    pour nfloor et nroommax ce sont des variables que je vais lire dans un fichier, ici j'ai écris directement la valeur actuelle pour mettre l'essentiel.
    Ensuite ça ne vient pas du comportement du programme.. Puisque j'ai créer un test.c ne contenant que le stricte minimum ( soit les variables dans un int main(void) ) et il y a une erreur..
    Donc je n'ai pas d'autres solutions que malloc ?

  4. #4
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Chercheur d'emploi
    Inscrit en
    Septembre 2007
    Messages
    7 485
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Chercheur d'emploi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2007
    Messages : 7 485
    Par défaut
    Citation Envoyé par Reverse_ Voir le message
    Ensuite ça ne vient pas du comportement du programme.. Puisque j'ai créer un test.c ne contenant que le stricte minimum ( soit les variables dans un int main(void) ) et il y a une erreur..
    Erreur qui est due au fait que les déclarations de tes tableaux dépassent la taille de la pile entière.

    Donc je n'ai pas d'autres solutions que malloc ?
    Si, mais ça dépend du contexte.

    La première chose à faire, dans un premier temps, est de ne déclarer les tableaux que dans les blocs ou les fonctions où tu en as réellement besoin si les données n'ont pas besoin de persister au delà d'un certain seuil, plutôt que tout déclarer en tête de programme si c'est pour ne s'en servir qu'occasionnellement. Ensuite, le plus propre consiste effectivement à allouer les ressources quand on en a besoin; et éventuellement libérer les précédentes, dans le cas d'un parcours linéaire d'un tableau par exemple. Si tu faisais le même travail sur papier, tu n'irais pas acheter d'emblée mille annuaires de pages blanches : tu prendrais un bloc, tu rangerais les résultats dans un classeur, et tu rachèterais éventuellement un nouveau bloc quand tu arriverais au bout du premier.

    C'est important également parce que ton programme n'est pas tout seul à utiliser les ressources de ta machine : les autres programmes en ont besoin aussi. Certes, ton application est la principale au moment où tu la fais fonctionner, mais imagine par exemple que le bloc-notes soit écrit de la même façon. Et que tu essaies de le faire fonctionner en même temps…

    D'autre part, il y a de fortes chances pour ce ne soit pas un hasard si tes n tableaux sont tous dimensionnés de la même façon : chacun d'eux doit probablement receler un attribut donné d'un même objet composite, qui apparemment semble être une pièce d'un labyrinthe ou une cellule d'un jeu de plateau.

    Et dans ce cas, le mieux est encore de déclarer une structure pour définir un nouveau type :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    struct MaCellule {
        int adjacent_hor;
        int adjacent_verh;
        int adjacent_verb;
     
        int adjacent_ver_bas;
        int door;
        int door_open;
     
        int nombre_parois;
    };
    … soit un seul attribut à chaque fois.
    Ensuite, tu définis un seul tableau de cellules :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
        struct MaCellule plan_de_jeu [nroommax+1][nfloor+1];
    … dans cet exemple, le problème n'est pas résolu car tu occupes exactement le même espace dans la pile, mais c'est beaucoup plus facile à structurer et surtout, à déclarer : tu n'as qu'un seul tableau (fût-il multidimensionnel) parce que tu n'as qu'un seul objet (qui lui contient tous les paramètres). En utilisant un pointeur de tableau, tu peux d'ailleurs utiliser un seul malloc() pour en réserver la place et conserver la même syntaxe dans le reste de ton code :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
        struct MaCellule (*plan_de_jeu)[nfloor+1];
     
        plan_de_jeu = malloc (sizeof (struct MaCellule) * (nroommax+1) * (nfloor+1);
    Ensuite, il faudra gérer les matrices creuses en empruntant des techniques utilisées dans les bases de données : si par exemple, tel ou tel paramètre, comme « hauteur_flamme », ne concerne que quelques cases sur le tableau entier, alors il vaut mieux déporter cela dans un tableau trié et distinct de structures qui contiendront le paramètre en question ET une référence vers la case concernée. La mémoire utilisée sera utilisée au plus juste et le temps de recherche dans le tableau annexe restera raisonnable puisque par définition, son contenu sera limité.

  5. #5
    Responsable Systèmes


    Homme Profil pro
    Gestion de parcs informatique
    Inscrit en
    Août 2011
    Messages
    18 261
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Gestion de parcs informatique
    Secteur : High Tech - Matériel informatique

    Informations forums :
    Inscription : Août 2011
    Messages : 18 261
    Par défaut
    Par rapport aux explications d'Obsidian, pourquoi ça marche sur Linux et pas sur Windows ? La taille de la pile ne doit pas être la même.
    Ma page sur developpez.com : http://chrtophe.developpez.com/ (avec mes articles)
    Mon article sur le P2V, mon article sur le cloud
    Consultez nos FAQ : Windows, Linux, Virtualisation

  6. #6
    Membre confirmé
    Homme Profil pro
    Lycéen
    Inscrit en
    Mars 2014
    Messages
    76
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 59
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Lycéen

    Informations forums :
    Inscription : Mars 2014
    Messages : 76
    Par défaut
    D'accord, je vous remercies pour vos explications, je vais retravailler tout ça !
    Merci,
    Cordialement, Reverse_

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

Discussions similaires

  1. Erreur segmentation fault sous NS2
    Par kadij dans le forum Développement
    Réponses: 6
    Dernier message: 12/07/2013, 15h07
  2. Réponses: 0
    Dernier message: 12/05/2011, 21h53
  3. Réponses: 5
    Dernier message: 23/12/2009, 11h31
  4. Réponses: 5
    Dernier message: 09/06/2009, 10h30
  5. Malloc et segmentation fault sous Linux
    Par Del4king dans le forum C
    Réponses: 16
    Dernier message: 15/11/2006, 17h10

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