109 votes

Pourquoi ce code est-il défaillant sur une architecture 64 bits mais fonctionne-t-il bien sur une architecture 32 bits ?

Je suis tombé sur le puzzle C suivant :

Q : Pourquoi le programme suivant présente-t-il un défaut de segmentation sur IA-64, mais fonctionne bien sur IA-32 ?

  int main()
  {
      int* p;
      p = (int*)malloc(sizeof(int));
      *p = 10;
      return 0;
  }

Je sais que la taille de int sur une machine 64 bits peut ne pas être la même que la taille d'un pointeur ( int peut être de 32 bits et le pointeur peut être de 64 bits). Mais je ne suis pas sûr que cela ait un rapport avec le programme ci-dessus. Avez-vous une idée ?

127voto

Flexo Points 39273

Le casting pour int* masque le fait que sans la bonne #include le type de retour de malloc est supposé être int . IA-64 se trouve avoir sizeof(int) < sizeof(int*) ce qui rend ce problème évident.

(Notez également qu'en raison du comportement non défini, il pourrait échouer même sur une plate-forme où sizeof(int)==sizeof(int*) est vrai, par exemple si la convention d'appel utilise des registres différents pour renvoyer des pointeurs et des entiers).

En FAQ comp.lang.c a un article qui traite de pourquoi couler le retour de malloc n'est jamais nécessaire et potentiellement mauvaise .

31voto

paxdiablo Points 341644

Très probablement parce que vous êtes ne comprenant pas le fichier d'en-tête pour malloc et, alors que le compilateur devrait normalement vous avertir de cela, le fait que vous intégrez explicitement la valeur de retour signifie que vous lui dites que vous savez ce que vous faites.

Cela signifie que le compilateur s'attend à un int à renvoyer de malloc qui est ensuite converti en pointeur. S'ils sont de tailles différentes, cela va vous causer des problèmes.

C'est pourquoi vous jamais lancer le malloc en C. Le void* qu'il renvoie sera implicitement converti en un pointeur de type correct (à moins que vous n'ayez pas inclus l'en-tête, auquel cas il vous aurait probablement averti de la conversion potentiellement dangereuse de int en pointeur).

10voto

curiousguy Points 2900

C'est pourquoi il ne faut jamais compiler sans avertissement sur les prototypes manquants.

C'est pour cela qu'en C, on n'utilise jamais le retour de malloc.

Le cast est nécessaire pour la compatibilité C++. Il y a peu de raisons (lire : aucune raison ici) de l'omettre.

La compatibilité C++ n'est pas toujours nécessaire, et dans certains cas pas du tout possible, mais dans la plupart des cas, elle est très facilement réalisable.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X