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 :

Erreur de segmentation


Sujet :

C

  1. #1
    Candidat au Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Décembre 2017
    Messages
    3
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 28
    Localisation : France, Deux Sèvres (Poitou Charente)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Finance

    Informations forums :
    Inscription : Décembre 2017
    Messages : 3
    Par défaut Erreur de segmentation
    Bonjour à tous,

    J'ai modélisé ici un graphe orienté pondéré par sa matrice d'adjacence (le coefficient de la i ème ligne et j ème est un nombre valant -1 si les sommets ne sont pas reliés et valant le poids de l'arc sinon).

    J'ai voulu faire une petite fonction permettant le connaitre le nombre de voisin d'un sommet donné mais le débugger m'indique une erreur de segmentation (j'ai encore un petit peu de mal à comprendre ce genre d'erreur ...).

    Voici ma fonction :
    Nom : fonction_nb_voisins.PNG
Affichages : 168
Taille : 10,0 Ko

    Je définis bien ma matrice d'adjacence dans le main avant d'appeler ma fonction, les sommets sont tous strictement positifs et j'ai bien fait attention à la taille de ma matrice.

    Merci de votre aide, je vous souhaite à tous de très bonnes fêtes

  2. #2
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Septembre 2007
    Messages
    7 448
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2007
    Messages : 7 448
    Par défaut
    Bonjour et bienvenue,

    Une « segfault » se produit lorsque tu lis ou écris en dehors de l'espace mémoire alloué à ton processus. C'est un dispositif qui s'appuie sur une fonctionnalité électronique du micro-processeur, exploitée par le système d'exploitation, qui consiste à définir globalement la zone utilisable par un processus avant son lancement et qui permet de demander directement audit micro-processeur de refuser d'honorer une instruction si elle sort de ce cadre et de déclencher à la place une exception, qui sera alors traitée par le système d'exploitation, lequel la gère d'ailleurs en mettant fin au processus fautif.

    C'est extrêmement fréquent : il suffit d'un pointeur mal initialisé, d'un accès abusif à une zone précédemment libérée ou même (dans le cas qui t'intéresse ici) tout simplement d'un dépassement de tableau. Et pourtant, jusqu'au milieu des années 1990, aucun des ordinateurs personnels n'était équipé d'une telle fonctionnalité. Un programme mal écrit avait donc toutes les chances de faire planter la machine entière, voire de provoquer des corruptions de données dans les cas les plus graves, mais ça faisait partie du métier…

    Dans ton programme, c'est visiblement le fait que tu accèdes à la case « sommet - 1 » à la ligne 39 qui pose problème. Il faudrait vérifier la valeur de ces indices durant l'exécution mais dans tous les cas, tu ne peux pas passer un tableau à plusieurs dimensions via « int ** » à ta fonction, si c'est bien un tableau multidimensionnel classique. Les dimensions du tableau ne sont PAS contenues dans ledit tableau, qui lui-même n'est pas un objet managé en soi. Les tableaux ne sont qu'une manière d'indexer une plage de données et leur dimensions ne sont connues que du compilateur seul. Il faut donc définir soigneusement le type du tableau pointé dans ta fonction.

    Pour être sûr de la façon dont tout cela fonctionne, il faudrait que l'on voie le reste de ton programme.

  3. #3
    Candidat au Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Décembre 2017
    Messages
    3
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 28
    Localisation : France, Deux Sèvres (Poitou Charente)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Finance

    Informations forums :
    Inscription : Décembre 2017
    Messages : 3
    Par défaut
    Merci de ta réponse Obsidian,
    J'ai remplacé le type matrice par un simple int**.
    En compilant j'ai un warning me disant que le type de matrice_adj est un int*[4] (dans mon exemple il y a 4 sommets) au lieu d'un int**, la fonction interprète donc mon tableau en 2D comme un simple tableau 1D d'où l'erreur de segmentation lorsque je demande "matrice_adj[sommet-1][i]" ?

    Mais alors comment pouvons-nous utiliser un tableau à 2 dimensions dans une fonction ?

    Le reste de mon programme se résume juste à l'initialisation du tableau dans le main et l'appelle de la fonction.

  4. #4
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Septembre 2007
    Messages
    7 448
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2007
    Messages : 7 448
    Par défaut
    Citation Envoyé par ValouF Voir le message
    Merci de ta réponse Obsidian, J'ai remplacé le type matrice par un simple int**. En compilant j'ai un warning me disant que le type de matrice_adj est un int*[4] (dans mon exemple il y a 4 sommets) au lieu d'un int**, la fonction interprète donc mon tableau en 2D comme un simple tableau 1D d'où l'erreur de segmentation lorsque je demande "matrice_adj[sommet-1][i]" ?
    Pas tout-à-fait. L'idée est qu'on ne peut pas passer la totalité d'un tableau par valeur en argument d'une fonction, d'abord parce que comme on l'a dit, ce n'est pas à proprement parler un objet à part entière mais plutôt une façon d'indexer les données, ensuite parce que ce tableau peut-être arbitrairement grand et qu'il faut absolument éviter de passer ça par la pile. C'est vrai aujourd'hui, et ça l'était encore plus en 1972 quand les premières versions du C ont commencé à être écrites.

    Ça veut donc dire que l'on est obligé, à la place, de passer un pointeur vers le tableau en question. La plupart du temps, avec les tableaux unidimensionnels, ça ne pose aucun problème puisque pointeur et tableau peuvent s'indexer de la même façon avec les crochets « [ ] » ou l'arithmétique des pointeurs. Et en fait, lorsque tu déclares un tableau, tu ne crées pas d'objet pointeur à proprement parler, tu ne fais que réserver l'espace occupé par ses éléments et pas un octet de plus, mais le nom du tableau (le symbole qui le représente en tant qu'instance, comme une variable) est lui résolu en l'adresse du tableau en mémoire, autrement dit en un pointeur vers son premier élément.

    L'arithmétique des pointeurs te permet alors de te déplacer à ±n fois la taille d'un élément par rapport à l'adresse de base. Et c'est aussi pour cette raison que tu peux faire un dépassement de tableau, tout comme tu peux dépasser la longueur d'un segment que tu aurais alloué avec malloc(). Toutes ces notions sont décorrélées entre elles.

    C'est important parce qu'on comprend bien, de cette façon, que l'on n'a pas spécialement besoin de connaître la taille d'un tableau pour se déplacer dedans… à condition que ce soit un tableau unidimensionnel. Mais quand tu déclares un tableau à plusieurs dimensions, par exemple int tableau[3][4][5], tu définis bien un tableau de la même façon qu'avant, soit ici la place exacte nécessaire à 3×4×5=60 entiers mais, tout comme avec les nombres entiers, la plus petite dimension est celle de droite. On a donc trois plages consécutives de quatre séquences de cinq entiers. L'ennui est que pour se déplacer le long d'une dimension (et savoir de combien avancer en mémoire à chaque fois), il faut connaître la longueur des dimensions inférieures.

    Tout cela pour dire que lorsque tu déclares un pointeur sur un tableau, seule la taille de la dimension la plus forte est facultative. Toutes les autres doivent être définies explicitement. D'où le int *[4] indiqué par le compilateur.

    Mais alors comment pouvons-nous utiliser un tableau à 2 dimensions dans une fonction ?
    Justement en utilisant le bon type, celui-là même qui t'est indiqué par ton compilateur. Soit tu as bien défini un type « matrice » avec typedef et, dans ce cas, c'est lui qu'il faut utiliser, soit tu as simplement déclaré un tableau à plusieurs dimensions et là, il faut utiliser int*[4] à la place de int **.

    Le seul moment où tu risques de rencontrer un problème, c'est si tu appelles ta fonction avec des tableaux de dimensions différentes. Comme cette information n'est pas intrinsèquement contenue dans le tableau, il faudra le faire explicitement, soit à travers des arguments passés à ta fonction, soit en définissant une structure qui recense le tout.

Discussions similaires

  1. Erreurs de segmentation !
    Par anti-conformiste dans le forum Applications et environnements graphiques
    Réponses: 16
    Dernier message: 18/10/2005, 11h11
  2. Erreur de segmentation
    Par Trunks dans le forum C
    Réponses: 3
    Dernier message: 06/10/2005, 18h28
  3. Erreur de segmentation (Inconnue)
    Par Dark-Meteor dans le forum C
    Réponses: 5
    Dernier message: 08/09/2005, 13h42
  4. [Dev-C++] Erreur de segmentation...
    Par sas dans le forum Dev-C++
    Réponses: 11
    Dernier message: 26/03/2005, 14h25
  5. erreur de segmentation
    Par transistor49 dans le forum C++
    Réponses: 10
    Dernier message: 15/03/2005, 11h18

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