2010-09-29 6 views
0

je fais quelque chose comme ça dans la boucle:fuite de mémoire lors de la manipulation char *

char* test = "\0"; 

test = strcat(test, somestr); 
... 
char* tmp = strstr(test, 0, len); 

free(test); 
test = tmp; 

Et obtenir fuite de mémoire. Ce que je fais mal?

+0

Rappelez-vous le formatage du code. –

+0

duplication possible de [pourquoi ce code crash?] (Http://stackoverflow.com/questions/2437318/why-does-this-code-crash) –

Répondre

3

Vous n'avez pas réellement de fuite de mémoire (dans le code que vous avez publié de toute façon), mais vous faites plusieurs choses mal.

char* test = "\0"; 

Ce déclare pointeur nommé test de et initialise pour pointer vers une série littérale de deux octets {0, 0}

test = strcat(test, somestr); 

Cette tente d'ajouter quelque chose à la fin de cette chaîne littérale (et comme une chaîne C est vide, elle serait comme une copie de chaîne). Les valeurs littérales sont souvent stockées dans une mémoire qui n'est pas accessible en écriture, donc la copie de quelque chose dans cette mémoire provoquerait probablement une erreur (erreur de segmentation ou SIGSEGV sur de nombreux systèmes d'exploitation). De plus, vous n'avez que deux octets de stockage pointés par test, ce qui signifie qu'à moins que somestr fasse référence à une chaîne dont strlen est inférieure ou égale à 1, vous finirez par essayer d'écrire sur une autre mémoire (quelle qu'elle soit) arrive après le "\ 0" que test points à).

char* tmp = strstr(test, 0, len); 

Je ne sais pas ce qui se passe ici depuis strstr ne prend que 2 arguments (les deux const char *).

free(test); 

Ici, vous tentez de libérer de la mémoire allouée sans segment de mémoire. Le tas est l'endroit où malloc, realloc et calloc obtiennent la mémoire qu'ils allouent. Appeler libre avec un emplacement de mémoire qui n'a pas été retourné par l'une de ces fonctions (et quelques autres fonctions sur certains systèmes) est une erreur car libre ne sait pas quoi faire avec eux.

Vous devriez probablement garder à l'esprit que souvent la mémoire est un énorme tableau d'octets, et que les pointeurs que vous utilisez sont comme des index de tableau. Le système que vous utilisez peut être capable de distinguer certaines zones de ce tableau et de déterminer comment vous pouvez y accéder (lisible, accessible en écriture et/ou exécutable). Mais ce n'est encore qu'un tableau d'octets. Lorsque vous avez une chaîne (telle que "foo") cela signifie que quelque part dans la RAM il y a quatre octets (3 lettres + l'octet de terminaison \ 0) et vous pouvez accéder à cette zone en connaissant son index dans le tableau d'octets qu'est la RAM. Il y a probablement d'autres choses qui sont stockées à côté de votre chaîne (par exemple { ..., 4, 2, 'f', 'o', 'o', 0, 99, 3, 2, ...}), vous devez donc essayer de vous assurer que vous restez dans l'espace de cette mémoire sans errer dans les données adjacentes.

1

Il y a quelques problèmes:

  1. strcat ajoutera une chaîne dans la mémoire tampon de destination. Le premier paramètre doit être un tampon et non un pointeur littéral de chaîne. Voici un exemple d'un tampon char ou aussi appelé un tableau de caractères: char test[1024];

  2. La valeur de retour de strcat est un pointeur vers la mémoire tampon de destination, il n'est pas une chaîne nouvellement allouée sur le tas. Donc, vous ne devriez pas appeler free sur la valeur de retour.

1

Vous ne pouvez pas strcat-test parce que vous êtes le pointant d'abord à une char * constante. Vous devez lui assigner de la mémoire. strcat ne le fera pas.

Changer votre code à quelque chose comme:

char* test = (char*)malloc(20*sizeof(char)); 
test[0] = '\0'; // nothing on this string to begin with 
strcat(test, "something"); 
free(test); 

De plus, cela ne fonctionnera pas:

char* tmp = strcat(test, 0, len); 

Comme il n'y a pas de fonction strcat avec trois paramètres.

Rappelez-vous. 99,9% du temps, il y aura un appel free pour chaque allocation malloc.

+0

Ensuite, j'ai une autre question. Comment puis-je supprimer les derniers k éléments du tampon? – Nikita

+0

Dans les chaînes C, vous ne "supprimez" pas les derniers éléments - vous déplacez le marqueur de fin '\ 0' pour terminer la chaîne à la nouvelle position. – Arkadiy

+0

Comment puis-je le faire? En passant, j'ai une chaîne au format Unicode. Cela signifie-t-il que je dois calculer non pas la longueur de la chaîne mais le dernier octet utile et mettre '\ 0' après? – Nikita