Rolinh

Rolinh' release

Quand Gcc Et Clang Ne Sont Pas D'accord

En jouant avec les sockets en C, je suis tombé hier sur une erreur que j’ai vraiment eu du mal à localiser.

En effet: en compilant mon programme avec gcc, il ne se comportait pas comme je le souhaitais mais en revanche, avec clang aucun soucis! Quand on en arrive là, on commence à se poser des questions… Au final j’ai trouvé mon erreur mais par contre je n’ai pas encore compris la différence de comportement entre clang et gcc.

Voilà ce qu’il se passait: dans une fonction, je déclarais une variable int qui se voyait modifiée après lecture dans une socket.

1
2
3
4
5
int e;
e = 0;
printf("e_1: %dn", e);
read(sockfd, shots, size);
printf("e_2: %dn", e);

Après exécution, le premier printf affiche bien 0 mais le second lui une valeur dans les choux (eg: -3485734) alors que la seule instruction entre les deux printf est la lecture dans une socket. Ça, c’est le comportement en compilant le code avec gcc. En le compilant avec clang en revanche, aucun problème: e garde bien sa valeur à 0. Bien évidemment, aucun warning de la part de clang ou gcc.

Maintenant, place à l’explication: Afin de comprendre, il manque des informations par rapport au code ci-dessus. En effet, il est nécessaire de savoir ce que sont sockfd, shots et size: sockfd est un paramètre de ma fonction

1
int sockfd

quand shots et size sont déclarés comme suit:

1
2
struct shot shots[NB_SHOTS];
int size = NB_SHOTS * sizeof(shots);

shots étant donc un tableau de type shot, déclaré comme suit:

1
2
3
4
struct shot{
  int x;
  int y;
};

Les plus aguerris d’entre vous auront déjà remarqué l’erreur: size aurait du être déclaré comme suit:

1
int size = NB_SHOTS * sizeof(struct shot);

Par conséquent, la mémoire allouée était insuffisante et la valeur de e se voyait donc écrasée par une autre. Une fois l’erreur corrigée, clang et gcc ont bien évidemment un comportement tout à fait similaire.

Là où je trouve curieux c’est l’absence de warning de la part des compilateurs et le comportement différent. En effet, il est normal qu’une erreur devait se produire: comportement du programme en étant compilé par gcc. En revanche, je n’arrive pas expliquer le fait que clang “corrigeait” mon erreur. Si je n’avais pas compilé mon programme avec gcc, je n’aurais peut-être pas mis la main sur mon erreur bien que je pense qu’il y aurait eu des répercussions plus tard.

Si une personne a le fin mot de l’histoire, je serais très heureux de l’entendre!