C++Talk.NET Forum Index C++Talk.NET
C++ language newsgroups
 
Archives   FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

delete []
Goto page 1, 2, 3  Next
 
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ (French)
View previous topic :: View next topic  
Author Message
Jean-Marie Epitalon
Guest





PostPosted: Mon Nov 20, 2006 4:59 pm    Post subject: delete [] Reply with quote



Bonjour,

quelqu'un pourrait-il me dire à quoi sert les [] dans l'instruction delete
[] comme dans l'exemple suivant:

int * ma_table = new int[10];
....
delete [] ma_table;

Je me demande pourquoi on en a besoin car en langage C, quand on libère de
la mémoire, on passe un pointeur à la fonction free() et c'est tout....
Merci
Jean-Marie
Back to top
Marc Boyer
Guest





PostPosted: Mon Nov 20, 2006 4:59 pm    Post subject: Re: delete [] Reply with quote



Le 20-11-2006, Jean-Marie Epitalon <be-dot-interlab (AT) atiscali (DOT) fr> a écrit :
Quote:
quelqu'un pourrait-il me dire à quoi sert les [] dans l'instruction delete
[] comme dans l'exemple suivant:

int * ma_table = new int[10];
...
delete [] ma_table;

Je me demande pourquoi on en a besoin car en langage C, quand on libère de
la mémoire, on passe un pointeur à la fonction free() et c'est tout....

Parce que le delete[] appelle les destructeurs de tous les
objets dans le tableau. Pour int, ça ne fait pas grand chose,
mais en général, c'est plus compliqué.

Marc Boyer
--
Si tu peux supporter d'entendre tes paroles
Travesties par des gueux pour exciter des sots
IF -- Rudyard Kipling (Trad. André Maurois)
Back to top
Marc Boyer
Guest





PostPosted: Mon Nov 20, 2006 4:59 pm    Post subject: Re: delete [] Reply with quote



Le 20-11-2006, Manuel Leclerc <manuel.leclerc (AT) alussinan (DOT) org> a écrit :
Quote:
Parce que le delete[] appelle les destructeurs de tous les
objets dans le tableau. Pour int, ça ne fait pas grand chose,
mais en général, c'est plus compliqué.

D'un autre côté, si delete[] peut faire ça, delete tout court
pourrait le faire aussi, non ?

J'imagine que oui, on pourrait considérer toute variable comme
un tableau de taille 1.
J'ai toujours imaginé qu'il devait y avoir un surcoût associé
au new[]/delete[] par rapport à new/delete, et que comme on
traque les surcouts en C++, on a offert les deux.
M'enfin bon, je miserais pas mon salaire sur cette hypothèse.

Marc Boyer
--
Si tu peux supporter d'entendre tes paroles
Travesties par des gueux pour exciter des sots
IF -- Rudyard Kipling (Trad. André Maurois)
Back to top
Manuel Leclerc
Guest





PostPosted: Mon Nov 20, 2006 7:40 pm    Post subject: Re: delete [] Reply with quote

Marc Boyer a écrit :

Quote:
Parce que le delete[] appelle les destructeurs de tous les
objets dans le tableau. Pour int, ça ne fait pas grand chose,
mais en général, c'est plus compliqué.

D'un autre côté, si delete[] peut faire ça, delete tout court
pourrait le faire aussi, non ?

--
This type of modern life
Is it for me?
This type of modern life
Is it for free?
Back to top
Jean-Marc Bourguet
Guest





PostPosted: Mon Nov 20, 2006 8:31 pm    Post subject: Re: delete [] Reply with quote

"Manuel Leclerc" <manuel.leclerc (AT) alussinan (DOT) org> writes:

Quote:
Marc Boyer a écrit :

Parce que le delete[] appelle les destructeurs de tous les
objets dans le tableau. Pour int, ça ne fait pas grand chose,
mais en général, c'est plus compliqué.

D'un autre côté, si delete[] peut faire ça, delete tout court
pourrait le faire aussi, non ?

Il faut liberer avec delete[] ce qui a ete alloue avec new[] comme il faut
liberer avec delete ce qui a ete libere avec new. On pourrait imaginer un
delete qui permette de faire les deux, mais
- on ne pourrait plus surcharger new[] et new independemment;
- tout ce qui est alloue avec new deviendrait plus gros pour stocker
l'information du nombre d'elements alloues.

A+

--
Jean-Marc
Back to top
Jean-Marc Desperrier
Guest





PostPosted: Tue Nov 21, 2006 12:32 am    Post subject: Re: delete [] Reply with quote

Jean-Marc Bourguet wrote:
Quote:
Il faut liberer avec delete[] ce qui a ete alloue avec new[] comme il faut
liberer avec delete ce qui a ete libere avec new. On pourrait imaginer un
delete qui permette de faire les deux,

Justement la plupart des implémentations "pardonnent" cette erreur et
font ce qu'il faut même avec le mauvais appel, non ?
Back to top
Alain Gaillard
Guest





PostPosted: Tue Nov 21, 2006 12:41 am    Post subject: Re: delete [] Reply with quote

Jean-Marc Desperrier a écrit :

Quote:
Justement la plupart des implémentations "pardonnent" cette erreur et
font ce qu'il faut même avec le mauvais appel, non ?

Souvent les implémentations se contentent d'invoquer les malloc et free
du C. Mais on ne peut pas compter sur ce que va faire une
implémentation. Et puis pour un même compîlateur, tu n'as aucune
garantie à ce niveau que la nouvelle version fera de même que l'ancienne.


--
Alain
Back to top
Jean-Marc Bourguet
Guest





PostPosted: Tue Nov 21, 2006 1:40 am    Post subject: Re: delete [] Reply with quote

Jean-Marc Desperrier <jmdesp (AT) alussinan (DOT) org> writes:

Quote:
Jean-Marc Bourguet wrote:
Il faut liberer avec delete[] ce qui a ete alloue avec new[] comme il faut
liberer avec delete ce qui a ete libere avec new. On pourrait imaginer un
delete qui permette de faire les deux,

Justement la plupart des implémentations "pardonnent" cette erreur et font
ce qu'il faut même avec le mauvais appel, non ?

* Je doute qu'il y ait des implémentations qui appellent les destructeurs
correctement quand on utilise delete plutôt que delete[].

* Dans le cas de new[] et delete[], le compilateur doit stocker le nombre
d'éléments alloués pour pouvoir faire ces appels. Le premier endroit qui
me vient à l'esprit, c'est d'allouer la taille d'un int (ou plus pour des
raisons d'alignement) en plus et de mettre ce nombre en tête de bloc.
Donc le compilateur dans le cas d'un appel à delete[] doit faire un
ajustement avant de passer le pointeur à operator delete[]. Ça ne
m'étonnerait pas que l'absence d'ajustement avec delete ne pardonne pas.
(Comme ce nombre est inutile dans le cas des POD, ça ne m'étonnerait pas
non plus qu'un compilateur optimise en le supprimant dans ce cas là,
auquel cas en effet l'appel à delete plutôt que delete[] pourrait passer
inapperçu jusqu'à l'ajout d'un destructeur ou l'implémentation d'une
autre politique d'allocation pour les tableaux...)

A+

--
Jean-Marc
FAQ de fclc++: http://www.cmla.ens-cachan.fr/~dosreis/C++/FAQ
C++ FAQ Lite en VF: http://www.ifrance.com/jlecomte/c++/c++-faq-lite/index.html
Site de usenet-fr: http://www.usenet-fr.news.eu.org
Back to top
Loïc Joly
Guest





PostPosted: Tue Nov 21, 2006 2:15 am    Post subject: Re: delete [] Reply with quote

Jean-Marc Desperrier a écrit :
Quote:
Jean-Marc Bourguet wrote:

Il faut liberer avec delete[] ce qui a ete alloue avec new[] comme il
faut
liberer avec delete ce qui a ete libere avec new. On pourrait
imaginer un
delete qui permette de faire les deux,


Justement la plupart des implémentations "pardonnent" cette erreur et
font ce qu'il faut même avec le mauvais appel, non ?

J'ai eu un vrai programme qui plantait avec un compilo non expérimental
(visual C++6), parce qu'on faisait delete après avoir fait new[]. En
plus le plantage était dans un endroit sans aucuns rapports, toujours
différent, seule une revue du code a permis de voir le problème, et de
constater le lien entre celui-ci et le plantage.

--
Loïc
Back to top
Sylvain
Guest





PostPosted: Tue Nov 21, 2006 6:05 am    Post subject: Re: delete [] Reply with quote

Jean-Marc Bourguet wrote on 20/11/2006 20:40:
Quote:

* Dans le cas de new[] et delete[], le compilateur doit stocker le nombre
d'éléments alloués pour pouvoir faire ces appels. Le premier endroit qui
me vient à l'esprit, c'est d'allouer la taille d'un int (ou plus pour des
raisons d'alignement) en plus et de mettre ce nombre en tête de bloc.

depuis des lustres, l'allocation prends 8 octets (sur archi. 32 bits) de
plus que demandée, un long pour stocker la taille d'un élément, un long
pour le nombre d'éléments; le ptr retourné est sur le bloc alloué + 8.

Quote:
(Comme ce nombre est inutile dans le cas des POD, ça ne m'étonnerait pas

non pas inutile, le bloc à libérer est toujours n * taille élement -- la
méthode concrête reçoit un void*, elle ne peut plus faire de sizeof ou
autre astuce, elle dépend nécessairement des infos du "header masqué".

Quote:
non plus qu'un compilateur optimise en le supprimant dans ce cas là,
auquel cas en effet l'appel à delete plutôt que delete[] pourrait passer
inapperçu jusqu'à l'ajout d'un destructeur ou l'implémentation d'une
autre politique d'allocation pour les tableaux...)

je ne pense pas qu'il est intérêt à virer ces infos, par contre il ne
fait rien de spécial sinon de libérer le bloc.

dans le cas d'instances, il doit appeler le destructeur sur chaque item
et peut faire des contrôles de heap plus poussés (pour par exemple
justement détecter des erreurs dans ces destructeurs) Studio fait cela
en mode Debug et un delete à la place d'un delete [] envoie aussitôt au
purgatoire.

Sylvain.
Back to top
Sylvain
Guest





PostPosted: Tue Nov 21, 2006 6:06 am    Post subject: Re: delete [] Reply with quote

Loïc Joly wrote on 20/11/2006 21:15:
Quote:

J'ai eu un vrai programme qui plantait avec un compilo non expérimental
(visual C++6), parce qu'on faisait delete après avoir fait new[]. En
plus le plantage était dans un endroit sans aucuns rapports, toujours
différent, seule une revue du code a permis de voir le problème, et de
constater le lien entre celui-ci et le plantage.

la portion de code n'avait jamais été vérifiée en mode debug alors.
(en effet en mode release, le tas peut être corrumpu et péter n'importe
où après).

Sylvain.
Back to top
Loïc Joly
Guest





PostPosted: Tue Nov 21, 2006 6:24 am    Post subject: Re: delete [] Reply with quote

Sylvain a écrit :
Quote:
Loïc Joly wrote on 20/11/2006 21:15:


J'ai eu un vrai programme qui plantait avec un compilo non
expérimental (visual C++6), parce qu'on faisait delete après avoir
fait new[]. En plus le plantage était dans un endroit sans aucuns
rapports, toujours différent, seule une revue du code a permis de voir
le problème, et de constater le lien entre celui-ci et le plantage.


la portion de code n'avait jamais été vérifiée en mode debug alors.
(en effet en mode release, le tas peut être corrumpu et péter n'importe
où après).

Ca date d'il y a quelques années, je ne me souviens donc plus des
détails... Mais il me semble bien que ça posait aussi des problèmes en
mode débug.

--
Loïc
Back to top
Jean-Marc Bourguet
Guest





PostPosted: Tue Nov 21, 2006 10:12 am    Post subject: Re: delete [] Reply with quote

Sylvain <noSpam (AT) mail (DOT) net> writes:

Quote:
Jean-Marc Bourguet wrote on 20/11/2006 20:40:
* Dans le cas de new[] et delete[], le compilateur doit stocker le nombre
d'éléments alloués pour pouvoir faire ces appels. Le premier endroit qui
me vient à l'esprit, c'est d'allouer la taille d'un int (ou plus pour des
raisons d'alignement) en plus et de mettre ce nombre en tête de bloc.

depuis des lustres, l'allocation prends 8 octets (sur archi. 32 bits) de
plus que demandée, un long pour stocker la taille d'un élément, un long
pour le nombre d'éléments; le ptr retourné est sur le bloc alloué + 8.

C'est une technique courante, popularisee par K&R, mais ce n'est pas la
seule.

Ce n'est d'ailleurs pas ce dont je parlais. Je parlais de la necessite de
stocker le nombre d'element dans le tableau alloue d'une facon connue par
le compilateur.

Quote:
(Comme ce nombre est inutile dans le cas des POD, ça ne m'étonnerait pas

non pas inutile, le bloc à libérer est toujours n * taille élement -- la
méthode concrête reçoit un void*, elle ne peut plus faire de sizeof ou
autre astuce, elle dépend nécessairement des infos du "header masqué".

D'une part quand tu peux definir ta propre allocation et que le compilateur
ne connait pas au moment ou il compile si tu le fais ou non, il n'a guere
le choix et ne peux pas compter sur ces infos cachees. Il doit dupliquer
celle dont il a besoin.

D'autre part, certains allocateurs allouent parfois plus que ce qui est
demande et alors ils stockent naturellement ce qui a ete alloue, pas ce qui
a ete demande.

Quote:
non plus qu'un compilateur optimise en le supprimant dans ce cas là,
auquel cas en effet l'appel à delete plutôt que delete[] pourrait passer
inapperçu jusqu'à l'ajout d'un destructeur ou l'implémentation d'une
autre politique d'allocation pour les tableaux...)

je ne pense pas qu'il est intérêt à virer ces infos, par contre il ne
fait rien de spécial sinon de libérer le bloc.

dans le cas d'instances, il doit appeler le destructeur sur chaque item et
peut faire des contrôles de heap plus poussés (pour par exemple justement
détecter des erreurs dans ces destructeurs) Studio fait cela en mode Debug
et un delete à la place d'un delete [] envoie aussitôt au purgatoire.

On va peut-etre etre plus clair avec un exemple:

$ cat sylvain.cpp
#include <iostream>
#include <stddef.h>
#include <stdlib.h>

struct Tag {} tag;

void* operator new[](size_t sz, Tag)
{
void* result = malloc(sz);
std::cout << "Allocation de " << sz << " bytes, resultat: " << result << '\n';
return result;
}

int main()
{
char* ptr = new(tag) char[9];
std::cout << "Allocation de 9 chars: " << (void*) ptr << '\n';
std::string* ptrs = new(tag) std::string[9];
std::cout << "Allocation de 9 strings(" << 9*sizeof(std::string) << "): " << (void*) ptrs << '\n';
}
$ g++-4.1.1 -Wall -Wextra -std=c++98 -pedantic-errors -o sylvain sylvain.cpp
$ ./sylvain
Allocation de 9 bytes, resultat: 0x215e0
Allocation de 9 chars: 0x215e0
Allocation de 40 bytes, resultat: 0x21be0
Allocation de 9 strings(36): 0x21be4
$ CC -o sylvain sylvain.cpp
$ ./sylvain
Allocation de 9 bytes, resultat: 41420
Allocation de 9 chars: 41420
Allocation de 44 bytes, resultat: 41bc8
Allocation de 9 strings(36): 41bd0

Tiens, il se passe exactement ce que j'ai ecrit avec g++ et sun CC. Un
appel a delete plutot que delete[] peut passer inappercu pour un tableau de
char, il a peut de chance de passer inappercu pour un tableau de string.

A+

--
Jean-Marc
Back to top
James Kanze
Guest





PostPosted: Tue Nov 21, 2006 10:12 am    Post subject: Re: delete [] Reply with quote

Sylvain wrote:
Quote:
Jean-Marc Bourguet wrote on 20/11/2006 20:40:

* Dans le cas de new[] et delete[], le compilateur doit stocker le nombre
d'éléments alloués pour pouvoir faire ces appels. Le premier endroit qui
me vient à l'esprit, c'est d'allouer la taille d'un int (ou plus pour des
raisons d'alignement) en plus et de mettre ce nombre en tête de bloc.

depuis des lustres, l'allocation prends 8 octets (sur archi. 32 bits) de
plus que demandée, un long pour stocker la taille d'un élément, un long
pour le nombre d'éléments; le ptr retourné est sur le bloc alloué + 8.

Ça dépend beaucoup des implémentations. Chez moi, un tableau des
int ne ajoute rien, quelque soit le compilateur, mais un tableau
d'un type avec un destructeur ajoute 8 octets, que ce soit avec
Sun CC ou avec g++, mais au moins avec Sun CC, je ne crois pas
que la taille de l'objet y est : le compilateur appelle une
fonction __Crun::vector_del avec l'adresse du tableau, la taille
de chaque élément, et l'adresse du destructeur. Je suppose donc
qu'il cherche le nombre d'éléments à partir de l'adresse du
tableau, mais non la taille de chaque élément, parce qu'on lui
la passe en paramètre.

Ce comportement, c'est à peu près ce que je me rappelle de
CFront. À partir de 2.1, en tout cas -- historiquement,
évidemment, il fallait fournir aussi le nombre d'éléments, c-à-d
delete [10] p.

Est-ce que tu ne confonds pas avec l'implémentation de malloc,
qui sert en-dessous des operator new ? Sauf que là non plus, je
ne connais pas d'algorithme répandu qui fonctionne comme ce que
tu as l'air de décrire ; surtout, à ce niveau-là, la taille de
l'élément est sans importance. (J'avoue ne jamais avoir vu
l'organisation que tu décris.

Quote:
(Comme ce nombre est inutile dans le cas des POD, ça ne
m'étonnerait pas

non pas inutile, le bloc à libérer est toujours n * taille élement -- la
méthode concrête reçoit un void*, elle ne peut plus faire de sizeof ou
autre astuce, elle dépend nécessairement des infos du "header masqué".

Oui, mais c'est gérer à un autre niveau, dans la fonction
operator new même (voire encore plus bas, dans malloc). Et là,
il existe beaucoup d'algorithmes différents, avec des
utilisations variées de la mémoire : des deux sur lesquelles j'ai
réelement travaillé, un se servait d'un simple pointeur à la
bloc prochain, et calculait la taille en faisait la différence
des pointeurs (et aux incontinuités dans l'arène, s'assurer
qu'il y avait un bloc factice toujours alloué à la fin de chaque
zone contiguë), l'autre arrondissait la taille toujours à la
puissance de deux suppérieur, et gérait autant de pools
séparés : lors de l'allocation, il mettait seulement
l'identificateur du pool avant l'adresse renvoyée.

Quote:
non plus qu'un compilateur optimise en le supprimant dans ce cas là,
auquel cas en effet l'appel à delete plutôt que delete[] pourrait passer
inapperçu jusqu'à l'ajout d'un destructeur ou l'implémentation d'une
autre politique d'allocation pour les tableaux...)

je ne pense pas qu'il est intérêt à virer ces infos, par contre il ne
fait rien de spécial sinon de libérer le bloc.

dans le cas d'instances, il doit appeler le destructeur sur chaque item
et peut faire des contrôles de heap plus poussés (pour par exemple
justement détecter des erreurs dans ces destructeurs) Studio fait cela
en mode Debug et un delete à la place d'un delete [] envoie aussitôt au
purgatoire.

En mode débogue, évidemment, on ajoute habituellement un préfixe
et un suffixe suffisamment pour détecter des cas de débordement.
Mais typiquement, ça se situe dans une couche intermédiaire
entre la couche de l'allocation proprement dite, et les operator
new[]/delete[]. Au moins qu'on modifie le code appelant, comme
fait Purify.

--
James Kanze (GABI Software) email:james.kanze (AT) gmail (DOT) com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Back to top
Sylvain
Guest





PostPosted: Tue Nov 21, 2006 8:20 pm    Post subject: Re: delete [] Reply with quote

Jean-Marc Bourguet wrote on 21/11/2006 09:21:
Quote:

C'est une technique courante, popularisee par K&R, mais ce n'est pas la
seule.

oui surement pas la seule, mais assez répandu.

Quote:
Ce n'est d'ailleurs pas ce dont je parlais. Je parlais de la necessite de
stocker le nombre d'element dans le tableau alloue d'une facon connue par
le compilateur.

ah pardon, moi je parlais de la façon dont le compilo stocke le nombre
d'éléments alloués ?!...

Quote:
[...]
Tiens, il se passe exactement ce que j'ai ecrit avec g++ et sun CC. Un
appel a delete plutot que delete[] peut passer inappercu pour un tableau de
char, il a peut de chance de passer inappercu pour un tableau de string.

c'est ce que j'ai dit, un type primitive (un POD) ne créé aucune
différence; pour des instances, un compilo un peu plus répandu comme vc
détecte l'erreur au runtime et ne peut pas laisser (sauf à ne rien
débugger) l'erreur inaperçue.

Sylvain.
Back to top
Display posts from previous:   
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ (French) All times are GMT
Goto page 1, 2, 3  Next
Page 1 of 3

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2006 phpBB Group
SEO toolkit © 2004-2006 webmedic.