web-dev-qa-db-fra.com

Allouer de la mémoire et sauvegarder une chaîne en c

Je me demandais pourquoi le code suivant ne fonctionnait pas

int main(int argc, char **argv)
{
     char *test = (char*) malloc(12*sizeof(char));
     test = "testingonly";
     free(test);
}

Après y avoir réfléchi, je partais du principe que j’allouais d’abord de la mémoire pour 12 caractères, mais que l’affectation de la ligne suivante crée un tableau de caractères sur la pile et que son adresse mémoire est testée. Donc free () essaie de libérer de l'espace sur la pile, ce qui n'est pas autorisé. Est-ce exact?

Alors, quelle serait la bonne approche pour enregistrer une chaîne sur le tas? Est-ce que le suivant est un chemin commun?

int main(int argc, char **argv)
{
     char *test = (char*) malloc(12*sizeof(char));
     strcpy(test, "testingonly");
     free(test);
}
20
pluckyDuck
char *test = (char*) malloc(12*sizeof(char));

        +-+-+-+-+-+-+-+-+-+-+-+-+
test--->|x|x|x|x|x|x|x|x|x|x|x|x|   (uninitialized memory, heap)
        +-+-+-+-+-+-+-+-+-+-+-+-+

test = "testingonly";

        +-+-+-+-+-+-+-+-+-+-+-+-+
test +  |x|x|x|x|x|x|x|x|x|x|x|x|
     |  +-+-+-+-+-+-+-+-+-+-+-+-+
     |  +-+-+-+-+-+-+-+-+-+-+-+-+
     +->|t|e|s|t|i|n|g|o|n|l|y|0|  
        +-+-+-+-+-+-+-+-+-+-+-+-+

free(test); // error, because test is no longer pointing to allocated space.

Au lieu de changer le pointeur test, vous devez copier la chaîne "testingonly" dans l'emplacement attribué à l'aide de, par exemple. strcpy ou utilisez strdup. Notez que des fonctions telles que malloc et strdup renvoient NULL si la mémoire est insuffisante, et doit donc être vérifiée.

char *test = (char*) malloc(12*sizeof(char));
strcpy(test, "testingonly");

        +-+-+-+-+-+-+-+-+-+-+-+-+
test--->|t|e|s|t|i|n|g|o|n|l|y|0|
        +-+-+-+-+-+-+-+-+-+-+-+-+

ou

char *test = strdup("testingonly");

        +-+-+-+-+-+-+-+-+-+-+-+-+
test--->|t|e|s|t|i|n|g|o|n|l|y|0|
        +-+-+-+-+-+-+-+-+-+-+-+-+
61
Anders

Vous avez déjà répondu à votre question. Strcpy est essentiellement le moyen approprié de copier une chaîne.

8
dicaprio

La première version ne crée pas de chaîne sur la pile, mais vous avez raison de dire que vous n'êtes pas autorisé à free après l'affectation. Les littéraux de chaîne sont généralement stockés dans des sections de mémoire constantes/en lecture seule. L'affectation ne copie rien, mais fait simplement que test pointe sur cette zone de mémoire. Vous ne pouvez pas le libérer. Vous ne pouvez pas non plus modifier cette chaîne.

Votre deuxième morceau de code est correct et habituel. Vous voudrez peut-être aussi regarder dans strdup si votre implémentation en est dotée.

5
Mat

Eh bien vous avez raison. Voyons maintenant le premier morceau de code.

char *test = (char*) malloc(12*sizeof(char));

Le code ci-dessus n'est pas un problème.

test = "testingonly";

Ici, vous avez modifié le pointeur test conduisant à une fuite de mémoire. Et lorsque vous essayez de libérer, vous ne libérez pas le pointeur réellement alloué, mais un littéral "testingonly" pointant vers. Les points littéraux indiquent une mémoire constante qui ne peut pas être remplacée dans les scénarios habituels.

En ce qui concerne maintenant le deuxième morceau de code, cela fonctionnera correctement si vous avez explicitement copié les données de l'endroit où le littéral réside dans le tas où votre test pointe.

Pour votre deuxième point, oui strcpy est un moyen habituel. Vous pouvez également utiliser "memcpy" si vous copiez des octets bruts.

Remarque: les littéraux ne sont pas stockés sur la pile. Mais vous ne pouvez pas modifier l'emplacement où les littéraux sont stockés.

4
havexz

le code

#include <stdio.h>
int main(int argc, char **argv)
{
     char *test = (char*) malloc(12*sizeof(char));
     strcpy(test, "testingonly");
     printf("string is: %s\n",test);
     free(test);
     return 0;
}

marchera 

0
Anes

Ceci est pour allouer la mémoire:

char *string;
string = (char *) malloc(15);

Ceci est pour sauvegarder les données:

strcpy(str, "kavitajain");
printf("String = %s,  Address = %u\n", str, str);
0
Kavita Jain