2011-06-20 3 views
1

J'ai une petite confusion dans le concept d'allocation de mémoire dynamique. Si nous déclarons qu'un pointeur indique un pointeur char, nous devons allouer suffisamment d'espace mémoire.Allocation de mémoire dynamique

char* str = (char*)malloc(20*sizeof(char)); 
str = "This is a string"; 

Mais cela fonctionnera également.

char* str = "This is a string"; 

Alors, dans quel cas devons-nous allouer de l'espace mémoire?

+6

Votre confusion concerne les pointeurs, pas l'allocation de mémoire dynamique. – ybungalobill

+0

Qu'essayez-vous de réaliser: Il y a une autre alternative: 'char str [] =" Ceci est une chaîne ";' –

+0

Pourquoi n'utilisez-vous pas 'std :: string'? –

Répondre

1

Les littéraux de chaîne sont un cas particulier dans la langue. Regardons de plus près votre code pour mieux comprendre cela:

D'abord, vous allouez une mémoire tampon en mémoire, et d'assigner l'adresse de cette mémoire à str:

char* str = (char*)malloc(20*sizeof(char)); 

Ensuite, vous attribuez une chaîne littérale à str . Cela va remplacer ce que str détenait précédemment, de sorte que vous perdrez votre tampon alloué dynamiquement, provoquant accidentellement une fuite de mémoire. Si vous souhaitez modifier le tampon alloué, vous devrez à un certain moment déréférencer str, comme dans str[0] = 'A'; str[1] = '\0';.

str = "This is a string"; 

Alors, quelle est la valeur de str maintenant?Le compilateur place tous les littéraux de chaîne dans la mémoire statique, de sorte que la durée de vie de chaque chaîne littérale dans le programme est égale à la durée de vie du programme entier. Cette instruction est compilée à une affectation simple similaire à str = (char*)0x1234, où 0x1234 est censé être l'adresse à laquelle le compilateur a mis la chaîne littérale.

Cela explique pourquoi cela fonctionne bien:

char* str = "This is a string"; 

S'il vous plaît noter également que la mémoire statique ne doit pas être changé lors de l'exécution, vous devez donc utiliser const char* pour cette mission.

Alors, dans quel cas devons-nous allouer de l'espace mémoire?

Dans de nombreux cas, par exemple lorsque vous devez modifier le tampon. En d'autres termes; lorsque vous devez pointer vers quelque chose qui ne peut pas être une constante de chaîne statique.

+0

'char * str =" Ceci est une chaîne ";' "ne fonctionne pas bien"; il est, en fait, à la fois dangereux et déconseillé. –

2

Dans le premier exemple, dynamiquement a alloué de la mémoire hors du tas. Il peut être modifié et doit être libéré. Dans le deuxième exemple, le compilateur a alloué de la mémoire statiquement, et il ne peut pas être modifié, et ne doit pas être libéré. Vous devez utiliser un const char*, et non un char*, pour que les chaînes littérales reflètent cela et garantissent une utilisation sûre.

7

En premier échantillon, vous avez une fuite de mémoire

char* str = (char*)malloc(20*sizeof(char)); 
str = "This is a string"; // memory leak 

adresse Numéroté sera remplacé par un nouveau. Nouvelle adresse est une adresse pour "Ceci est une chaîne".

Et vous devriez changer le deuxième échantillon.

const char* str = "This is a string"; 

En raison de "Ceci est une chaîne" est la zone protégée en écriture.

+0

Dans ce cas, j'ai besoin d'un malloc, quand je peux faire simplement char * str = "ceci est une chaîne"; – cppcoder

+0

Ceci est une autre question. Si vous écrivez 'char * str =" ceci est une chaîne ";' vous n'êtes pas autorisé à changer les caractères de votre chaîne. Si vous écrivez 'char * str = new char [20]', vous pouvez remplacer n'importe quel caractère: 'str [13] = 'a';'. –

+0

Maintenant, j'ai compris pourquoi mon programme se bloquait quand j'essayais de modifier un 'char *'. Donc, en fait, il devrait toujours être 'const char *'. Alors pourquoi 'char *' existe-t-il? – cppcoder

1

Dans le premier exemple, vous faites juste des erreurs. Vous allouez de la mémoire dynamique sur le tas et laissez str pointer vers lui. Ensuite, vous laissez simplement str pointer vers une chaîne de caractères et la mémoire allouée est divulguée (vous ne copiez pas la chaîne dans la mémoire allouée, il vous suffit de changer l'adresse pointée str, vous devrez utiliser strcpy dans le premier exemple) .

1

Je veux ajouter à Alexey Malistov's Answer en ajoutant que vous pouvez éviter la fuite de mémoire dans votre premier exemple en copiant « Ceci est une chaîne » à str comme dans le code suivant:

char* str = (char*)malloc(20*sizeof(char)); 
strcpy(str, "This is a string"); 

S'il vous plaît, notez que par peut Je ne veux pas vous ont à. C'est juste ajouter à une réponse pour ajouter de la valeur à ce fil.

+0

Comment allez-vous suivre l'afflux de réponses? Il y avait comme 1 réponse quand j'ai commencé à taper ma réponse, et après l'affichage il y a comme 6 réponses. –

4

Le vraisemblablement C++ 98 extrait de code

char* str = (char*)malloc(20*sizeof(char)); 
str = "This is a string"; 

effectue les opérations suivantes: (1) alloue 20 octets, stocker le pointeur vers ce bloc de mémoire dans str, et (2) stocke un pointeur vers un littéral chaîne, dans str. Vous n'avez plus aucun moyen de vous référer au bloc alloué précédemment, et vous ne pouvez donc pas le libérer. Vous avez perdu la mémoire.

Notez que depuis str a été déclaré comme char*, le compilateur ne peut pas détecter pratiquement si vous essayez d'utiliser pour modifier le littéral. Heureusement, en C++ 0x, cela ne va pas compiler . J'aime vraiment ce changement de règle!

L'extrait de code

char* str = "This is a string"; 

stocke un pointeur sur une chaîne de caractères dans une variable char* nommée str, tout comme dans le premier exemple, et comme cet exemple, il ne sera pas compilé avec C++ 0x compilateur. Au lieu de cette bêtise, utilisez par exemple std::string de la bibliothèque standard, et saupoudrez const généreusement dans votre code.

Vive & HTH.,

2

Attribution à une variable char* fait pointer à autre chose, alors pourquoi avez-vous allouez la mémoire en premier lieu si vous oubliez immédiatement à ce sujet? C'est une fuite de mémoire. Vous avez probablement voulu dire ceci:

char* str = (char*)malloc(20*sizeof(char)); 
strcpy(str, "This is a string"); 
// ... 
free(str); 

Cela va copier la deuxième chaîne à la première. Depuis cela est taggés C++, vous devez utiliser un std::string:

#include <string> 

std::string str = "This is a string"; 

Aucune allocation de mémoire manuelle et la libération nécessaire, et l'affectation fait ce que vous pensez.