Fonctionnement de la mémoire (c++)

Le problème exposé dans ce sujet a été résolu.

Bonjour voici un petit code :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
#include <iostream>
#include "Header.h"

int main()
{
    char* buffer = new char [8];


    std::cout << &buffer << std::endl;

    delete[] buffer;
    std::cout << &buffer << std::endl;
    return 0;
}

1- Crée un espace de 8 bits char (buffer) 2- Afficher l’adresse de buffer 3- Supprimer buffer 4- Afficher l’adresse de buffer

Quand je compile j’ai ça comme résultat :

Console

Question, donc quand j’utilise delete[], c’est le contenus et non la variable buffer qui est supprimée, donc buffer devien NULL ? Si c’est ça, comment je peux faire pour supprimer la variable elle-même ?

+0 -0

Quand tu utilises new, tu alloues dans une zone memoire qui s’appelle le tas, où tu geres explicitement la memoire. Ton pointeur ou (presque) toute autre variable allouée autrement est allouée sur la pile, c’est a dire qu’elle sera automatiquement detruite a la sortie du scope correspondant.

Lorsque tu appelles delete, tu supprimes la zone en memoire. Il faut mettre le pointeur a NULL/nullptr, sinon tu es vulnerable face a des attaques use-after-free et des bugs logiciels.

Attention, buffer est une variable qui n’a pas grand chose à voir avec la zone mémoire allouée.

Elle stocke juste la première adresse de la zone mémoire allouée.

Donc, delete[] ne va pas toucher à la variable buffer. delete[] va désalouer la zone mémoire sur laquelle pointe buffer.

+1 -0

Si c’est ça, comment je peux faire pour supprimer la variable elle-même ?

PixarFilmz

buffer est soumis aux mêmes règles de portée que toutes variables, il a juste un type un peu particulier. La portée de buffer s’arrête donc à la fin du bloc d’instruction, c’est une variable locale.

La taille d’une variable d’adresse varie selon les systèmes, mais c’est environ équivalent à celle d’un int, c’est donc souvent insignifiant, négligeable, y a t-il vraiment une nécéssité à l’économie de cet espace ?

Tu peux jouer sur les portées en l’isolant dans son propre bloc d’instruction.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
#include <iostream>
#include "Header.h"

int main()
{
    // opérations préalables, buffer n'est pas encore déclaré, donc pas encore alloué
    {
        char* buffer = new char [8]; // allocation sur le tas de 8 char et allocation sur la pile d'une pointeur initialisé à l'adresse des 8 char

        std::cout << &buffer << std::endl;

        delete[] buffer; // désallocation des 8 char du tas
        std::cout << &buffer << std::endl; // buffer est toujours sur la pile
    } // désallocation de buffer sur la pile
    std::cout << &buffer << std::endl; // erreur à la compilation, buffer n'existe pas

    return 0;
}

Pour préciser, il faut différencier encore deux choses, la portée et la durée d’une variable.

La porté c’est où tu peux utiliser l’identifiant. La durée c’est la période pendant laquelle tu peux utiliser la variable allouée.

Pour la variable buffer de l’exemple, les deux sont confondues … Mais ce n’est plus le cas pour une variable globale ou pour une variable statique.

+0 -0

La porté c’est où tu peux utiliser l’identifiant. La durée c’est la période pendant laquelle tu peux utiliser la variable allouée.

ache

:o les termes c’est pas portée et visibilité ?
où la portée est justement ce que tu désigne par durée et visibilité ce que tu désigne par portée ?

+0 -0

1- Crée un espace de 8 bits char (buffer)

Plutôt "réclames un tableau de 8 x 1 char (1 octet) = 8 octets contigue"

2- Afficher l’adresse de buffer

Pas vraiment; ce que tu fais actuellement (en utilisant l’opérateur &), c’est que tu affiches l’adresse qui contient l’adresse du tableau. Pour afficher l’adresse du tableau, il te suffit d’écrire :

std::cout << buffer << std::endl;

car buffer contient déjà une adresse.

4- Afficher l’adresse de buffer

Cf. 2

Question, donc quand j’utilise delete[], c’est le contenus et non la variable buffer qui est supprimée, donc buffer deviens NULL ?

Lorsque tu utilises delete[], l’opérateur va regarder ta variable buffer, et va demander à l’allocateur mémoire de libérer la mémoire que tu avais allouée via new (et l’allocateur sait qu’à l’adresse contenue par buffer, il y a 8 octets alloués).

Sache que quand tu appelles l’opérateur delete, il ne remettra pas forcément ta variable à NULL, c’est à toi de le faire; de la même manière, la mémoire rendue ne sera pas remise à zéro.

Si c’est ça, comment je peux faire pour supprimer la variable elle-même ?

En C++, les variables sont déclarées dans un bloc, qui est généralement représenté par les accolades. Si tu sors de ce bloc (donc que tu atteins l’accolade fermante à ton bloc), le compilateur va "détruire" cette variable (qui n’est qu’une étiquette pour une valeur).

1- Crée un espace de 8 bits char (buffer)

Plutôt "réclames un tableau de 8 x 1 char (1 octet) = 8 octets contigue"

ntimeu

Bien vu, du coup si l’objectif est de manipuler un groupement de bits, la classe bitset du standard est faite pour ça.

2- Afficher l’adresse de buffer

Pas vraiment; ce que tu fais actuellement (en utilisant l’opérateur &), c’est que tu affiches l’adresse qui contient l’adresse du tableau. Pour afficher l’adresse du tableau, il te suffit d’écrire :

std::cout << buffer << std::endl;

car buffer contient déjà une adresse.

ntimeu

bah il affiche bien l’adresse de la variable buffer, et c’est bien ce qu’il dit. à voir s’il a fait une erreur, par abus de langage, qui colle bien avec ce qu’il a codé, mais pour moi il a bien saisi cette notion.

La porté c’est où tu peux utiliser l’identifiant. La durée c’est la période pendant laquelle tu peux utiliser la variable allouée.

ache

:o les termes c’est pas portée et visibilité ?
où la portée est justement ce que tu désigne par durée et visibilité ce que tu désigne par portée ?

leroivi

Il ne me semble pas …

Pas d’après Wikipédia. Portée.

PS: Le terme de durée est un peu plus difficile à justifier Portée Dynamique

PPS: En anglais Portée (ou Visibilité plus rarement) -> Scope (Ou visibility) et Durée -> Extent (ou lifetime).

+0 -0
Connectez-vous pour pouvoir poster un message.
Connexion

Pas encore membre ?

Créez un compte en une minute pour profiter pleinement de toutes les fonctionnalités de Zeste de Savoir. Ici, tout est gratuit et sans publicité.
Créer un compte