Le code suivant ne contient aucune boucle, ni goto , ni récursivité; pourtant il imprime de 1 à 10 dans la console.
#include <stdio.h>
int n = 1;
void foo() {
int x;
printf("%d ", n);
if (++n>10) return;
*(&x+4) -= 5;
}
int main() {
foo();
return 0;
}
Ce code mystérieux * (& x + 4) - = 5; est à l'origine de la boucle. p >
Autant que j'ai compris - la valeur de x est conservée dans la mémoire de la pile. Ainsi peut-être, avant que (& x + 4) il y a le pointeur de la fonction foo , et foo est appelé récursivement. p>
Là encore, je ne suis pas sûr que mes hypothèses soient exactes. Je ne comprends pas non plus d'où vient ce 5 . J'ai essayé d'imprimer et d'analyser les adresses (conseillées par mon collègue) du pointeur de fonction et des variables; et associez-les à ma connaissance de la disposition de la mémoire C . Mais je suis devenu plus confus.
S'il y avait plus de variables déclarées avant et après x , comment * (& x + 4) - = 5; code> changerait?
OS: Windows-7 64 bits, Compilateur: GNU GCC, Editeur: strong > CodeBlocks 16.01
3 Réponses :
Le comportement de * (& x + 4) - = 5; n'est pas défini car il écrit en dehors des limites de tout objet alloué par le programme. Ce que cela fera dépendra de ce qui sera stocké à cette adresse, le cas échéant. Donc, la réponse courte à la raison pour laquelle votre code se comporte si étrangement est que le code a un bogue qui rend son comportement imprévisible.
Ce qui se passe probablement sur votre plate-forme, c'est qu'elle finit probablement par modifier l'adresse à laquelle elle revient, la faisant revenir à main avant l'appel à foo résultant en main appelant à nouveau foo .
Ce n'est pas parce que le code n'est pas valide en C ou C ++ qu'il est nécessairement bogué. S'il est livré avec des instructions qu'il est destiné à être compilé avec une version spécifique de GCC pour Windows 7, cela dépend du comportement du compilateur. Ce n'est peut-être même pas un comportement non documenté.
Je n'ai jamais vu de document de compilateur quelque chose comme ça. S'il repose sur un comportement non documenté, c'est bogué. Il n'y a aucun moyen de savoir dans quelles conditions le comportement se produira ou ne se produira pas.
David a raison. Lorsqu'un code essaie d'écrire ou même d'accéder à quelque chose dans le bloc mémoire qui ne lui est pas alloué, il peut faire n'importe quoi (même une explosion nucléaire s'il y a, disons, l'adresse d'une fonction qui fait chier avec le réacteur). Il est de votre responsabilité de prendre en charge les allocations de mémoire car C n'est pas un langage fortement typé. C'est juste une co-incidence qui provoque une boucle. Sur mon système, cela fonctionne comme prévu.
Vous modifiez la pile dans * (& x + 4) - = 5; C'est un comportement indéfini, et sous un comportement non défini, tout est permis, même pour faire voler des démons hors de votre nez . Voir http://catb.org/jargon/html/N/nasal-demons .html
Peut-être que pour un HW spécifique avec un compilateur spécifique, vous obtenez toujours le même comportement, mais ce n'est pas nécessaire.
Il imprime uniquement
1puis quitte.Cela dépend d'un comportement non défini. Vous n'êtes pas censé déréférencer une mémoire à
(& x + 4)lorsquexest simplementint x.@Deanie J'ai utilisé le compilateur gcc. Imprime 1 à 10 en C et C ++.
@TheDeepThinker J'ai utilisé le compilateur gcc. Imprime 1 avec un espace, puis sort.
@SouravGhosh J'ai trouvé le code en ligne. Je sais, je ne devrais pas coder comme ça. Je veux simplement connaître l ' explication .
Code auto-modifiable reposant sur la disposition de la pile et les détails de l'architecture matérielle. Cette question est inutile sans ces détails fournis. Par ex. sur mon Fedora 29 x86_64 avec gcc 8.2.1 je n'obtiens qu'un défaut de segmentation. Pas de surprise là-bas, pour être honnête ...
@StefanBecker Ce n'est pas du "code auto-modifiable", c'est juste corrompre sa propre pile.
@duskwuff Merci pour votre commentaire. Pourriez-vous s'il vous plaît dire comment la pile est corrompue.
@duskwuff dans mon livre modifier l'adresse de retour sur la pile est un code auto-modifiable.
@StefanBecker Dans mon livre, ce n'est que du "code auto-modificateur" s'il s'agit de code modificateur . La pile est constituée de données, pas de code.