Pourquoi ce code ne provoque-t-il pas une erreur de segmentation?

Pourquoi cette erreur de segmentation n’est-elle pas?

#include  int main() { int i; int arr[] = {1, 2, 3, 4}; for(i=0;i<8;i++) { arr[i] = i; printf(" %d", arr[i]); } printf("\n"); return 0; } 

Mais cela se produit lorsque je remplace 8 par 9 dans la boucle for.

Remarque: je l’essaie sur linux crunchbang 32 bits

Techniquement, ce programme entraîne un comportement indéfini , ce qui signifie qu’il n’y a absolument aucune garantie de ce que ce programme est autorisé à faire. Il pourrait en principe formater votre disque dur, envoyer des messages désagréables à tous vos amis, mettre le feu à votre ordinateur ou devenir un élément sensible et asservir l’humanité.

Dans ce cas, le comportement non défini lorsque n = 8 arrive à ne rien faire de mal, alors que le comportement non défini lorsque n = 9 provoque un segfault. Les deux sont des comportements totalement autorisés pour le programme, mais rien ne garantit qu’ils soient portables.

J’espère que cela t’aides!

@templatetypedef a raison; il m’a battu à la réponse. Un comportement indéfini ne signifie pas nécessairement segfault.

Mais je voudrais faire quelques spéculations quant à la raison pour laquelle il segfaults pour n = 9 mais pas 8. Normalement, des variables comme int i et int arr[] résident sur la stack , ce qui augmente. Donc, i pourrais résider à l’adresse 0x4000 , et si c’est un 0x4000 de 4 octets, alors arr[0] est à 0x4004 , arr[1] est à 0x4008 , et ainsi de suite. Dans ce cas, le compilateur aura probablement alloué 16 octets pour arr et il utilisera peut-être des adresses inférieures à 0x4014 (le premier octet après arr , c’est-à-dire l’adresse de arr[5] ). Mais il y a généralement d’autres éléments sur la stack en plus des variables que vous déclarez manuellement. Par exemple, les arguments de l’appel printf sont probablement sur la stack et il pourrait y avoir d’autres informations de comptabilité. Donc, si arr[9] coïncide avec l’emplacement de la stack que le compilateur utilise pour autre chose, vous masquerez cette information par inadvertance, ce qui pourrait entraîner une erreur de segmentation.

Si arr[8] trouve au bas de votre cadre de stack alloué par le système d’exploitation, votre système d’exploitation aura configuré votre processeur pour refuser littéralement d’exécuter toute instruction permettant de charger ou de stocker une valeur à partir de l’adresse qui coïncide avec arr[9] . Je pense que ce scénario est peu probable, étant donné que la taille des stacks est généralement de 4 Ko environ et que, pour un programme aussi court, vous devriez être loin de la fin de la stack allouée.

La réponse de templatetypedef est correcte, il s’agit d’un comportement indéfini (ce qui n’est pas aussi rare que vous pourriez le penser) mais j’aimerais append quelque chose:

9 * sizeof (int) n’est pas une puissance de 2. Lorsque les compilateurs allouent de la mémoire, ils allouent généralement une puissance de deux octets pour éviter la fragmentation du tas .

Vous vous demandez peut-être pourquoi il n’a pas atsortingbué 4 * sizeof (int), car ce serait exactement ce que vous aviez demandé. Je ne suis pas sûr, mais il se peut que le compilateur alloue quelques octets supplémentaires ou qu’il dispose d’une quantité de mémoire minimale à allouer pour les tableaux. Cela dépend du compilateur et des options avec lesquelles vous avez compilé votre code.

Essayez d’exécuter votre code sans optimisations (-O0 sur la ligne de commande), il pourrait au lieu de cela allouer la quantité exacte de mémoire dont vous avez besoin et segfault pour i> = 4.

Je peux me tromper cependant, je ne suis pas sûr que les compilateurs C allouent des tableaux statiques dans le tas ou la stack.