quand la mémoire est effacée sur la stack pour une fonction locale?

Je veux savoir quand exactement la mémoire est effacée de la stack allouée aux appels de fonction locaux. J’ai vu dans certains tutoriels vidéo que l’appel de fonction est renvoyé à la mémoire principale et que la mémoire allouée à la fonction locale est effacée. J’ai quelques questions sur le programme ci-dessous, veuillez expliquer.

#include void print(){ printf("testing \n"); } int* sum(int* a, int* b){ int c = *a + *b; return &c; } int main(){ int a=3,b=2; int *ptr = sum(&a,&b); print(); printf("sum is: %d",*ptr); return 0; } 

Lorsque j’exécute le programme ci-dessus, c’est l’impression de la valeur résiduelle qui est attendue. Mais si je commente la fonction “print ()” dans le programme principal, puis l’exécution du programme, elle affiche la valeur correcte de la sum.

  1. Cela signifie-t-il que, même si l’exécution de la fonction locale est terminée dans la stack, tant qu’il n’y a pas d’autre appel de fonction à la stack, la mémoire allouée précédemment n’est pas effacée?

  2. Si je supprime l’instruction “printf” dans “print ()” et que je garde l’appel “print ()” en tant que main, je pourrais voir le résultat de sum comme d’habitude. Pourquoi n’a-t-il pas écrasé la mémoire en stack?

C n’a pas de stack, le mot stack n’est même pas mentionné dans la norme (C89, C99 ou C11). Une implémentation peut utiliser une stack pour fournir les aspects comportementaux de la machine abstraite C, mais c’est la machine abstraite elle-même que le standard spécifie.

Donc, quand la stack est effacée (en supposant qu’elle existe même), c’est quelque chose qui dépend totalement de la mise en œuvre. Ce que vous faites est essentiellement un comportement indéfini, qui consiste à accéder à un object une fois que sa durée de vie est terminée afin que les résultats puissent être ceux que l’implémentation choisit.

Pour ce qui est des raisons pour lesquelles vous pouvez accéder aux éléments après la fin de leur durée de vie pour une implémentation spécifique , cela est probablement dû au fait que l’entrée et la sortie d’une fonction n’efface pas la stack, elle règle simplement le pointeur mémoire aussi).

Ainsi, à moins que quelque chose écrase ce qui se trouve sur cet emplacement de mémoire (par exemple, un appel ultérieur à printf ), il restra probablement tel qu’il avait été défini pour la dernière fois.

À titre d’exemple, voici un exemple de code prolog pour une fonction:

 push ebp ; Save the frame pointer. mov ebp, esp ; Set frame pointer to current stack pointer. sub esp, XX ; Allocate XX space for this frame. 

et son épilogue équivalent:

 mov esp, ebp ; Restore stack pointer. pop ebp ; Get previous frame pointer. ret ; Return. 

Notez que ni l’allocation d’espace ( sub dans le prolog) ni sa désallocation ( mov dans l’épilogue) n’efface réellement la mémoire utilisée.

Cependant, comme indiqué, ce n’est pas une chose sur laquelle vous devriez compter.

La réponse à votre question dépend du système d’exploitation. Dans un système qui crée un processus à partir de zéro (VMS / NT), la stack n’est effacée que lors de la création du processus. La stack est créée à partir de pages sans demande. Lorsque vous accédez à une page de stack pour la première fois, le système d’exploitation crée une nouvelle page zéro.

Dans les systèmes de forking, la stack est effacée chaque fois qu’un nouvel exécutable est chargé. Habituellement, le processus est le même que ci-dessus.

Une fois la stack créée, tout ce qui y est placé y rest jusqu’à écrasement.

La stack est gérée par le système d’exploitation. pas les langages de programmation.