Ordre de déclaration dans struct

a marqué ce sujet comme résolu.

Bonjour, si dans struct Master je déclare int x; avant struct One * pOne; j’ai un erreur Segmentation 11. Mais si je déclare int x; avant, cela compile.

Et si je n’appelle pas la fonction writeData(&master); je n’ai pas d’erreur.

Où chercher ? Que comprendre ? Merci !😁

struct One{
	int num1;
};

struct Master{
	struct One * pOne;
	int x;
}; // ---> Donne erreur Segmentation 11

// struct Master{
// 	int x;
// 	struct One * pOne;
// }; // ---> Compilera correctement.

void writeData(struct Master * m){
	m->pOne->num1 = 10;
	printf("num1 = %d\n", m->pOne->num1);
}

int main (void){

	struct Master master;

	writeData(&master);

	return 0;
}```

Bonjour,

On ne peut pas utiliser un pointeur auquel on n’a pas affecté de valeur.
Par exemple m a bien une valeur, c’est l’adresse de master.
Mais m->pOne n’a pas reçu de valeur, d’où effectuer m->pOne->num1 est ce que l’on appelle un Undefined Behavior.

Le "Undefined Behavior" peut tout produire comme par exemple planter, ou pire le code continue et on n’a aucune idée de ce qui se passe!
Changer l’ordre pour ton code produit deux effets différents.

Si tu utilise gcc, il y a des analyzeurs pour diagnostiquer ce genre de problème: -fanalyzer (cela ne les active pas tous, il faut lire le man pour savoir ce qu’il y a dedans).

$ gcc -fanalyzer test.c
test.c: In function ‘void writeData(Master*)’:
test.c:18:12: warning: use of uninitialized value ‘*m.Master::pOne’ [CWE-457] [-Wanalyzer-use-of-uninitialized-value]
   18 |         m->pOne->num1 = 10;
      |         ~~~^~~~
  ‘int main()’: events 1-3
    |
    |   22 | int main (void){
    |      |     ^~~~
    |      |     |
    |      |     (1) entry to ‘main’
    |   23 | 
    |   24 |         struct Master master;
    |      |                       ~~~~~~
    |      |                       |
    |      |                       (2) region created on stack here
    |   25 | 
    |   26 |         writeData(&master);
    |      |         ~~~~~~~~~~~~~~~~~~
    |      |                  |
    |      |                  (3) calling ‘writeData’ from ‘main’
    |
    +--> ‘void writeData(Master*)’: events 4-5
           |
           |   17 | void writeData(struct Master * m){
           |      |      ^~~~~~~~~
           |      |      |
           |      |      (4) entry to ‘writeData’
           |   18 |         m->pOne->num1 = 10;
           |      |         ~~~~~~~
           |      |            |
           |      |            (5) use of uninitialized value ‘*m.Master::pOne’ here
           |

(À ne pas utiliser avec les sanitizers, car pour une raison que j’ignore, certains désactivent les analyseurs.)

jo_link_noir, -fanalyser (et autres options) me serait intéressant, mais bien que je compile avec commande gcc etc.., la commande analyzer n’existe pas chez moi. Quand je demande la version de mon gcc j’obtiens : Apple clang version 11.0.0 (clang-1100.0.33.17) Là, je ne sais que faire. Merci ! :)

Je pensais que tu aurais compris le commentaire de dalfab. Ce n’est apparamment pas le cas.

Je ne vois pas la définition d’un objet de type One dans le main.

Ni l’assignation du pointeur pOne dans la structure master du main.

Les définitions de structure au début du code ne créent aucun objet. Elles disent seulement au compilateur de quoi auront l’air ces structures.

C’est dans le main que tu as créé un objet de type Master.

P.S. Pour mettre en commentaire plusieurs lignes consécutives, on peut faire comme suit:

/*
 ... lignes en commentaires ...
 */

C’est valide en C, C++ et Rust.

+0 -0

jo_link_noir, -fanalyser (et autres options) me serait intéressant, mais bien que je compile avec commande gcc etc.., la commande analyzer n’existe pas chez moi. Quand je demande la version de mon gcc j’obtiens : Apple clang version 11.0.0 (clang-1100.0.33.17) Là, je ne sais que faire. Merci ! :)

iguanodon

C’est une "entourloupe" d’Apple. Gcc est un alias de clang, car les 2 compilateurs sont dans l’ensemble compatible, ce qui ne gêne pas la plupart du temps. Pour un vrai gcc, il faut l’installer (avec brew ?).

Au passage, ta version de clang me semble un peu vieille. Sur mon PC j’ai la version 18 et la CI MacOS de github action la version 15. Mais pour du C cela ne devrait pas causer de problème (le langage n’évolue pas beaucoup).

@jo_link_noir

C’est vrai que le langage C n’évolue pas boucoup (ou pas du tout ?).

Mais le compilateur peut être amélioré pour générer du code plus performant ou détecter plus d’erreurs.

@iguanodon

Je rappoorte ici les lignes de fin de structures:

}; // ---> Donne erreur Segmentation 11
}; // ---> Compilera correctement.

Le code compilera sans erreur peu importe dans quel ordre tu places les champs x et pOne.

L’erreur vient du fait que le champs pOne de la structure master dans le main n’est pas initialisé (je l’ai déjà mentionné).

Je t’ai déjà dit ce qu’il manque.

Il ne faut pas confondre les erreurs décelées à la compilation et les erreurs qui surviennent à l’exécution.

+0 -0
Connectez-vous pour pouvoir poster un message.
Connexion

Pas encore membre ?

Créez un compte en une minute pour profiter pleinement de toutes les fonctionnalités de Zeste de Savoir. Ici, tout est gratuit et sans publicité.
Créer un compte