Tableau de caractères C ++ [] fuite de mémoire [dupliquer]

Aug 18 2020

j'ai créé char arr [] et lui assigne une chaîne littérale

char arr[] = "some string";                  // arr occupies 12 chars in memory
std::cout << std::strlen(arr)  << std::endl; // lenght is 11 chars + 1 null-terminator
                                             //arr[11] is '\0'

Ensuite, je mets un terminateur nul dans l'élément 6

arr[5] = '\0';
std::cout << std::strlen(arr) << std::endl; // lenght is 5 chars  + 1 null-terminator
  1. Est-ce une fuite de mémoire?
  2. Comment le compilateur saura-t-il qu'il doit libérer de la mémoire après le premier '\ 0'? (quand supprimera la variable arr)
  3. Est-il possible de changer la longueur de cette variable arr et de notifier au compilateur combien il devrait libérer lors de la suppression de la variable?

Réponses

5 user253751 Aug 18 2020 at 13:03
  1. Est-ce une fuite de mémoire?

Non.

  1. Comment le compilateur saura-t-il qu'il doit libérer de la mémoire après le premier '\ 0'? (quand supprimera la variable arr)

La variable est de 12 caractères. C'est la même chose que d'écrire:

char arr[12] = "some string";

Ainsi, il libèrera toujours 12 caractères. La variable est un tableau de 12 caractères; le fait que le 6ème caractère soit '\ 0' est complètement hors de propos.

Au fait, une fois que vous avez défini le 6ème caractère sur '\ 0', vous êtes toujours autorisé à utiliser les 12 caractères, car il s'agit toujours d'un tableau de 12 caractères. Même ceux après le '\ 0'. Mais vous ne pouvez pas y stocker 13 caractères.

  1. Est-il possible de changer la longueur de cette variable arr et de notifier au compilateur combien il devrait libérer lors de la suppression de la variable?

Non. Il n'est pas possible de modifier la taille d'une variable.

6 cigien Aug 18 2020 at 13:03

Dans ce code:

char arr[] = "some string";

la variable arrest un tableau statique de taille fixe. Il n'y a pas d'allocation de mémoire dynamique ici, et il n'y a donc pas lieu de s'inquiéter des fuites de mémoire. Le compilateur s'occupera de la mémoire, quel que soit le contenu dans lequel vous écrivez arr.

2 JoopEggen Aug 18 2020 at 13:07

Par souci d'exhaustivité.

Il n'y a pas non plus de fuite de mémoire dans la mémoire allouée, comme dans:

char* arr = (char*) malloc(12);
strcpy(arr, "some string");
arr[6] = '\0';
free(arr);

La gestion de la mémoire passe par la mémoire allouée (12), pas par l'utilisation sous-jacente (nul-terminated char *). (Style C, C ++ également)

1 Slava Aug 18 2020 at 13:56

On dirait que vous l'avez en arrière. La taille du tableau en C ++ ne peut pas être modifiée, point final. En raison de ce fait et du fait que si vous passez un tableau en tant que pointeur, vous perdez des informations de taille réelle de cet accord de tableau a été créé pour les chaînes de style C - 0 octet aka \0aka terminateur nul traité comme une fin dynamique de la chaîne. Accord signifie que les fonctions fonctionnant avec des chaînes de style C traitent cela comme une terminaison de chaîne. Cela vous permet d'utiliser un tableau de taille fixe pour des chaînes de longueur différente et de ne transmettre qu'un seul pointeur sans taille de mémoire réelle aux fonctions à lire (par exemple, imprimer à l'écran). Remarquez que lorsque vous passez un tableau de caractères à des fonctions qui y écrivent des données, vous devez souvent lui dire quelle est la taille réelle du tableau, afin que cette fonction n'accède pas à la mémoire en dehors des limites car ces fonctions ignorent le terminateur nul s'il est déjà là.

Voilà, cet accord se produit sur différentes couches gérées par les baies. Ainsi, quelles que soient les données que vous mettez dans ce tableau, n'affecteraient pas sa taille du point de vue du langage, pour le compilateur C ++, vous avez créé un tableau de taille fixe, vous y mettez des données et quand sa durée de vie est arrivée, le compilateur le détruit comme un tableau de taille fixe. Peu importe si vous y mettez zéro octet ou pas.

VladfromMoscow Aug 18 2020 at 13:16

Une fuite de mémoire se produit lorsqu'une mémoire a été allouée par le programmeur à l'aide de l'opérateur newet n'a pas été supprimée à l'aide de l'opérateur deleteou delete [].

Dans cette déclaration

char arr[] = "some string"; 

C'est la mémoire allouée au compilateur (ou au système) pour le tableau de caractères arr qui a soit la durée de stockage automatique, soit la durée de stockage statique. Ainsi, le compilateur (ou le système) est responsable de libérer la mémoire allouée. L'adresse de la mémoire allouée est connue du compilateur (ou du système).

Utiliser cette déclaration

arr[5] = '\0';

vous n'avez pas réaffecté le tableau. Vous venez de modifier son contenu plus précisément d'un seul octet.

Comment le compilateur saura-t-il qu'il doit libérer de la mémoire après le premier '\ 0'? (quand supprimera la variable arr)

Parce que le compilateur (ou le système) sait comment l'objet du type tableau a été déclaré.

Pour l'objet, 12 octets ont été alloués.

char arr[] = "some string"; 

Est-il possible de changer la longueur de cette variable arr et de notifier au compilateur combien il devrait libérer lors de la suppression de la variable?

Je pense que vous voulez dire la taille de l'objet. Non, vous ne pouvez pas modifier la taille de l'objet car ce n'est pas vous qui avez alloué la mémoire pour l'objet.

Vous pouvez réallouer l'objet si vous avez utilisé l'opérateur newpour l'allouer comme par exemple

char *arr = new char[12];

std::strcpy( arr, "some string" );

//...

char *tmp = new char[20];

strcpy( tmp, "another " );
strcat( tmp, arr );

delete [] arr;
arr = tmp;