Cette question vise à améliorer ma compréhension de
ce que je peux et ne peux pas faire avec les pointeurs lors de l'allocation et de la libération:

Le code ci-dessous n'est pas destiné à s'exécuter, mais configure simplement une situation pour les questions ci-dessous.

char *var1  = calloc(8,sizeof(char));
char **var2 = calloc(3,sizeof(char*));

var1 = "01234567";

var1[2] = '\0';
var1[5] = '\0';

//var1 = [0][1][\0][3][4][\0][6][7]

var2[0] = var1[0];
var2[1] = var1[3];
var2[2] = var1[6];

free(var1);
free(var2);

Donné l'extrait suivant

1: est-il possible d'écrire dans un emplacement après le \ 0 si vous connaissez la taille que vous avez allouée.

2: Puis-je faire ce que j'ai fait avec var2, s'il pointe vers un bloc vers lequel un autre pointeur pointe?

3: les appels gratuits sont-ils corrects? ou mourra gratuitement en raison du \ 0 situé dans var1.
J'ai imprimé toutes les variables après free, et seules celles jusqu'au premier null ont été libérées (changées en null ou en d'autres caractères étranges et normaux). Est-ce que ça va?

4: Tout autre élément que vous souhaitez signaler qui est complètement faux et qui doit être évité.

Merci beaucoup.

2
Octavio del Ser 20 nov. 2018 à 01:53

4 réponses

Meilleure réponse

Ok, récapitulons simplement ce que vous avez fait ici:

char *var1  = calloc(8,sizeof(char));
char **var2 = calloc(3,sizeof(char*));

Donc var1 est (un pointeur vers) un bloc de 8 caractères, tous mis à zéro \0. Et var2 est (un pointeur vers) un bloc de 3 pointeurs, tous définis sur NULL.

Alors maintenant, c'est la mémoire du programme, il peut en faire ce qu'il veut.

Pour répondre spécifiquement à vos questions ~

Il est tout à fait normal d'écrire des caractères à l'intérieur de votre bloc char. C'est un modèle de programmation courant pour analyser les tampons de chaîne en écrivant un \0 après une section de texte pour utiliser les opérations de chaîne C quotidiennes sur celle-ci, puis pointez sur le caractère suivant après l'ajout de \0 et continuez l'analyse.

var2 est simplement un tas de pointeurs de caractères, il peut pointer vers n'importe quel caractère nécessaire, il ne doit pas nécessairement être au début de la chaîne.

Les appels à free() sont quelque peu OK (sauf pour le bogue - voir ci-dessous). Il est normal que le contenu des blocs free () d soit écrasé lorsqu'ils sont renvoyés dans la pile, donc ils semblent souvent contenir des caractères "poubelles" s'ils sont imprimés par la suite.

Il y a quelques problèmes avec l'attribution de var1 ~

var1 = "01234567";

Ici, vous dites "var1 pointe maintenant vers cette chaîne constante". Votre compilateur a peut-être généré un avertissement à ce sujet. Premièrement, le code attribue un const char* à un char* (les chaînes codées en dur sont const, mais les compilateurs C ne préviendront que de cela [EDIT: c'est vrai pour C ++, pas C, voir le commentaire de nm] ). Et deuxièmement, le code a perdu toutes les références au bloc de mémoire que var1 utilisait pour pointer. Vous ne pouvez plus jamais free() cette mémoire - elle a fui. Cependant, à la fin du programme, le free() essaie d'opérer sur un pointeur vers un bloc de mémoire (le "01234567") qui n'a pas été alloué sur le tas. C'est mauvais. Puisque vous quittez immédiatement, il n'y a pas d'effets néfastes, mais si c'était au milieu de l'exécution, la prochaine allocation (ou la prochaine 1000e!) Pourrait planter bizarrement. Ces types de problèmes sont difficiles à déboguer.

Probablement ce que vous auriez dû faire ici (je suppose que votre intention) est une copie de chaîne:

strncpy(var1, "01234567", 8);

Avec cette opération au lieu de l'affectation, tout va bien. En effet, les chiffres sont stockés dans la mémoire allouée sur line1.

1
Kingsley 19 nov. 2018 à 23:40

var1 = "01234567"; n'est pas correct car vous attribuez une valeur de pointeur vers const char vers un pointeur vers mutable char et provoque une fuite de mémoire car la valeur de pointeur vers a {{ X4}} le tampon alloué de 8 char stocké dans la variable var1 est perdu. Il semble que vous ayez en fait l'intention d'initialiser le tableau alloué avec la valeur de la chaîne littérale à la place (bien que cela nécessite l'allocation d'un tableau de 9 éléments). L'affectation var1[2] = '\0'; provoque un comportement indéfini car l'emplacement vers lequel var1 pointe n'est pas modifiable. var2[0] = var1[0]; est également faux car vous attribuez une valeur de char au pointeur vers char. Enfin, free(var1); essaiera de désallouer un pointeur vers une chaîne littérale de mémoire tampon, pas quelque chose que vous avez alloué.

0
user7860670 19 nov. 2018 à 23:26

Les pointeurs ne fonctionnent pas de cette façon.

Si quelqu'un a écrit

int a = 6*9;
a = 42;

Vous vous demanderiez pourquoi ils ont pris la peine d'initialiser a à 6*9 en premier lieu - et vous auriez raison. Il n'y a aucune raison de le faire. La valeur renvoyée par * est simplement oubliée sans être utilisée. Il ne pourrait jamais être calculé en premier lieu et personne ne saurait la différence. C'est exactement équivalent à

int a = 42;

Maintenant, quand des pointeurs sont impliqués, il y a une sorte de voie neuronale maléfique dans notre cerveau qui essaie de nous dire qu'une séquence d'énoncés qui est exactement comme celle illustrée ci-dessus fonctionne différemment. Ne faites pas confiance à votre cerveau. Ça ne l'est pas.

char *var1  = calloc(8,sizeof(char));
var1 = "01234567";

Vous vous demanderiez pourquoi ils ont pris la peine d'initialiser var1 sur calloc(8,sizeof(char)); en premier lieu - et vous auriez raison. Il n'y a aucune raison de le faire. La valeur renvoyée par calloc est simplement oubliée sans être utilisée. Il ne pourrait jamais être calculé en premier lieu et personne ne saurait la différence. C'est exactement équivalent à

char* var1 = "01234567";

... ce qui pose problème, car vous ne pouvez pas modifier les chaînes littérales.

Ce que vous voulez probablement , c'est

char *var1  = calloc(8, 1);     // note sizeof(char)==1, always
strncpy (var1, "01234567", 8);  // note not strcpy — you would need 9 bytes for it

Ou une variation de cela.

1
n. 'pronouns' m. 19 nov. 2018 à 23:20

Question 4 - Quel est le problème

Vous «appelez» de la mémoire et stockez un pointeur vers elle dans var1. Ensuite, vous exécutez var1 = "01234567" qui stocke un pointeur vers une chaîne littérale dans var1, perdant ainsi la mémoire appelée. J'imagine que vous pensiez copier une chaîne. Utilisez strcpy ou similaire.

Ensuite, vous écrivez des valeurs nulles dans ce vers quoi var1 pointe. Comme il s'agit d'une chaîne littérale, elle peut échouer si le littéral est en mémoire en lecture seule. Le résultat n'est pas défini.

free(var1) ne va pas bien avec un pointeur vers un littéral. Votre code peut échouer ou vous pouvez obtenir une corruption de tas.

1
dave 19 nov. 2018 à 23:05