web-dev-qa-db-fra.com

qu'est-ce que l'écrasement de pile (C)?

Code:

int str_join(char *a,  const char *b) {
   int sz =0; 
   while(*a++) sz++;  
   char *st = a -1, c;  
   *st = (char) 32;
   while((c = *b++)) *++st = c;  
   *++st = 0;
   return sz;
}

....

char a[] = "StringA"; 
printf("string-1 length = %d, String a = %s\n", str_join(&a[0],"StringB"), a);

Production:

string-1 longueur = 7, char * a = StringA StringB

*** Écrasement de pile détecté ****:/T02 terminé

Abandonné (core dumpé)

Je ne comprends pas pourquoi cela montre smashing de pile? et qu'est-ce que * pile fracassant? Ou est-ce l'erreur de mon compilateur?

5
Gonzalez

Eh bien, écrasement de pile ou débordement de tampon de pile est un sujet assez détaillé pour être discuté ici, vous pouvez vous référer à cet article wiki pour plus d'informations.

En ce qui concerne le code affiché ici, le problème est que votre tableau a n'est pas assez grand pour contenir le résultat final concaténé.

Ainsi, en disant

 while((c = *b++)) *++st = c;

vous accédez essentiellement à une mémoire hors limite qui invoque comportement indéfini . C'est la raison pour laquelle vous obtenez le problème de "destruction de pile" parce que vous essayez d'accéder à une mémoire qui n'appartient pas à votre processus.

Pour résoudre ce problème, vous devez vous assurer que le tableau a contient suffisamment d'espace pour contenir à la fois la première et la seconde chaîne concaténées ensemble. Vous devez fournir un tableau de destination plus grand, en bref.

7
Sourav Ghosh

Le smashing de pile signifie que vous avez écrit en dehors de ("smashed" past/through) l'espace de stockage de la fonction pour les variables locales (cette zone est appelée "stack", dans la plupart des systèmes et langages de programmation). Vous pouvez également trouver ce type d'erreur appelé "débordement de pile" et/ou "débordement de pile".

Dans votre code, C place probablement la chaîne pointée par a sur la pile. Dans votre cas, l'endroit qui provoque le smash de pile est lorsque vous incrémentez st au-delà du pointeur a d'origine et écrivez à l'endroit où il pointe, vous écrivez en dehors de la zone garantie par le compilateur C avoir réservé la chaîne d'origine affectée à a.

Chaque fois que vous écrivez en dehors d'une zone de mémoire qui est déjà correctement "réservée" en C, c'est un "comportement indéfini" (ce qui signifie simplement que le langage/standard C ne dit pas ce qui se passe): généralement, vous finissez par écraser autre chose dans la mémoire de votre programme (les programmes placent généralement d'autres informations juste à côté de vos variables sur la pile, comme les adresses de retour et d'autres détails internes), ou votre programme essaie d'écrire en dehors de la mémoire que le système d'exploitation l'a "autorisé" à utiliser. Dans les deux cas, le programme se casse généralement, parfois immédiatement et évidemment (par exemple, avec une erreur de "défaut de segmentation"), parfois de manière très cachée qui ne devient évidente que bien plus tard.

Dans ce cas, votre compilateur crée votre programme avec des protections spéciales pour détecter ce problème et ainsi vos programmes se terminent avec un message d'erreur. Si le compilateur ne faisait pas cela, votre programme essaierait de continuer à s'exécuter, sauf qu'il pourrait finir par faire la mauvaise chose et/ou planter.

La solution se résume à avoir besoin de dire explicitement à votre code d'avoir suffisamment de mémoire pour votre chaîne combinée. Vous pouvez le faire en spécifiant explicitement la longueur du tableau "a" pour être suffisamment longue pour les deux chaînes, mais cela n'est généralement suffisant que pour des utilisations simples où vous savez à l'avance l'espace dont vous avez besoin. Pour une solution à usage général, vous utiliseriez une fonction comme malloc pour obtenir un pointeur vers un nouveau morceau de mémoire du système d'exploitation qui a la taille dont vous avez besoin/voulez une fois que vous avez calculé ce que le plein la taille va être (n'oubliez pas d'appeler free sur les pointeurs que vous obtenez à partir de malloc et de fonctions similaires une fois que vous en avez terminé).

3
mtraceur