OVH Cloud OVH Cloud

delete []

39 réponses
Avatar
Jean-Marie Epitalon
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

10 réponses

1 2 3 4
Avatar
James Kanze
Sylvain wrote:
James Kanze wrote on 22/11/2006 09:41:


[...]
D'après ce que j'ai cru comprendre des discussions lancées par des gens
utilisant VC++ et ayant des problèmes, ce qu'il fait c'est utiliser des
macros pour substituer aux appels à new et new[] des appels à un n ew/new[]
avec placement pour fournir des d'informations pour un allocateur de d ebug.


Je ne crois pas. En tout cas, il accepte des new de placement,
ce qui pose des problèmes avec des macros.


j'avais également mal lu ce point.

il n'y a pas (je n'ai jamais vu) de 'placement new' avec Studio (et j'ai
arrêté d'en faire en abandonnant le Pascal et son absolute).


Mais si. Le placement new fonction très bien. Il fonctionnait
déjà avec VC++ 6.0, d'ailleurs.

Mais c'est vrai qu'on ne s'en sert pas tous les jours. Je m'en
servais dans mes tableaux pré-norme, où je faisais à peu près ce
que fait la STL, c-à-d séparer l'allocation et la construction,
mais je crois que c'est le seul endroit où ça me servait.

--
James Kanze (GABI Software) email:
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



Avatar
Laurent Deniau
James Kanze wrote:
Sylvain wrote:

James Kanze wrote on 22/11/2006 09:41:



[...]

D'après ce que j'ai cru comprendre des discussions lancées par des gens
utilisant VC++ et ayant des problèmes, ce qu'il fait c'est utiliser des
macros pour substituer aux appels à new et new[] des appels à un new/new[]
avec placement pour fournir des d'informations pour un allocateur de debug.





Je ne crois pas. En tout cas, il accepte des new de placement,
ce qui pose des problèmes avec des macros.




j'avais également mal lu ce point.



il n'y a pas (je n'ai jamais vu) de 'placement new' avec Studio (et j'ai
arrêté d'en faire en abandonnant le Pascal et son absolute).



Mais si. Le placement new fonction très bien. Il fonctionnait
déjà avec VC++ 6.0, d'ailleurs.

Mais c'est vrai qu'on ne s'en sert pas tous les jours. Je m'en
servais dans mes tableaux pré-norme, où je faisais à peu près ce
que fait la STL, c-à-d séparer l'allocation et la construction,
mais je crois que c'est le seul endroit où ça me servait.


tu ne fais jamais de new dans un ctor? Ou alors tu ne cherches pas a
ecrire du code 'exception safe'.

a+, ld.




Avatar
James Kanze
Laurent Deniau wrote:
James Kanze wrote:
Sylvain wrote:

James Kanze wrote on 22/11/2006 09:41:


[...]

D'après ce que j'ai cru comprendre des discussions lancées
par des gens utilisant VC++ et ayant des problèmes, ce
qu'il fait c'est utiliser des macros pour substituer aux
appels à new et new[] des appels à un new/new[] avec
placement pour fournir des d'informations pour un
allocateur de debug.


Je ne crois pas. En tout cas, il accepte des new de placement,
ce qui pose des problèmes avec des macros.


j'avais également mal lu ce point.

il n'y a pas (je n'ai jamais vu) de 'placement new' avec Studio (et j'ai
arrêté d'en faire en abandonnant le Pascal et son absolute).


Mais si. Le placement new fonction très bien. Il fonctionnait
déjà avec VC++ 6.0, d'ailleurs.

Mais c'est vrai qu'on ne s'en sert pas tous les jours. Je m'en
servais dans mes tableaux pré-norme, où je faisais à peu près ce
que fait la STL, c-à-d séparer l'allocation et la construction,
mais je crois que c'est le seul endroit où ça me servait.


tu ne fais jamais de new dans un ctor? Ou alors tu ne cherches pas a
ecrire du code 'exception safe'.


Un placement new, jamais. D'ailleurs, les new normaux dans le
corps d'un constructeur sont assez rare, précisement parce que
je tiens à être exception safe. (Quand j'y pense -- les new
tout court sont pas si fréquents. Ce n'est pas du Java, après
tout. Et dans un constructeur, il sont vraiment rare, en dehors
de l'idiome du pare-feu de compilation.)

--
James Kanze (Gabi Software) email:
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





Avatar
Sylvain
James Kanze wrote on 23/11/2006 16:10:

[...]

il n'y a pas (je n'ai jamais vu) de 'placement new' avec Studio (et j'ai
arrêté d'en faire en abandonnant le Pascal et son absolute).


Mais si. Le placement new fonction très bien. Il fonctionnait
déjà avec VC++ 6.0, d'ailleurs.


je n'ai pas dit qu'il ne "fonctionnait" pas !

bien sur que depuis que VC fait du C++ (ou à peu près), l'opérateur new
peut être surchargé, VC5 comme 6 définissent (dans new.h):

inline void* operator new(size_t, void* _P)
{return (_P); }

et cela fonctionne.

Sylvain.


Avatar
Laurent Deniau
James Kanze wrote:
Laurent Deniau wrote:

James Kanze wrote:

Sylvain wrote:




James Kanze wrote on 22/11/2006 09:41:





[...]




D'après ce que j'ai cru comprendre des discussions lancées
par des gens utilisant VC++ et ayant des problèmes, ce
qu'il fait c'est utiliser des macros pour substituer aux
appels à new et new[] des appels à un new/new[] avec
placement pour fournir des d'informations pour un
allocateur de debug.







Je ne crois pas. En tout cas, il accepte des new de placement,
ce qui pose des problèmes avec des macros.






j'avais également mal lu ce point.





il n'y a pas (je n'ai jamais vu) de 'placement new' avec Studio (et j'ai
arrêté d'en faire en abandonnant le Pascal et son absolute).





Mais si. Le placement new fonction très bien. Il fonctionnait
déjà avec VC++ 6.0, d'ailleurs.




Mais c'est vrai qu'on ne s'en sert pas tous les jours. Je m'en
servais dans mes tableaux pré-norme, où je faisais à peu près ce
que fait la STL, c-à-d séparer l'allocation et la construction,
mais je crois que c'est le seul endroit où ça me servait.




tu ne fais jamais de new dans un ctor? Ou alors tu ne cherches pas a
ecrire du code 'exception safe'.



Un placement new, jamais. D'ailleurs, les new normaux dans le
corps d'un constructeur sont assez rare, précisement parce que
je tiens à être exception safe. (Quand j'y pense -- les new
tout court sont pas si fréquents. Ce n'est pas du Java, après
tout. Et dans un constructeur, il sont vraiment rare, en dehors
de l'idiome du pare-feu de compilation.)


Tout a fait. Je voulais juste profiter de l'occasion pour rappeler que
le seul moyen d'etre exception safe dans un constructeur qui utilise new
etait d'utiliser un 'placement new', histoire de decourager les
debutants d'utiliser new ;-)

a+, ld.






Avatar
Loïc Joly

Tout a fait. Je voulais juste profiter de l'occasion pour rappeler que
le seul moyen d'etre exception safe dans un constructeur qui utilise new
etait d'utiliser un 'placement new', histoire de decourager les
debutants d'utiliser new ;-)


Je ne sais pas trop de quel niveau d'exception safety tu parles, mais
j'ai du mal à voir le problème avec du code comme celui là (sans
placement new) :

struct C
{
C(double d);
private:
boost::shared_ptr<double> myD;
};

C::C(double d) : myD(new double(d))
{
}


--
Loïc

Avatar
Laurent Deniau
Loïc Joly wrote:


Tout a fait. Je voulais juste profiter de l'occasion pour rappeler que
le seul moyen d'etre exception safe dans un constructeur qui utilise
new etait d'utiliser un 'placement new', histoire de decourager les
debutants d'utiliser new ;-)



Je ne sais pas trop de quel niveau d'exception safety tu parles, mais
j'ai du mal à voir le problème avec du code comme celui là (sans
placement new) :

struct C
{
C(double d);
private:
boost::shared_ptr<double> myD;
};

C::C(double d) : myD(new double(d))
{
}


Parce que tu as pris un type trivial, mais remplace double par T
(template class) ou meme std::string, et le probleme est bien la.

a+, ld.


Avatar
Michel Decima
Loïc Joly wrote:

Je ne sais pas trop de quel niveau d'exception safety tu parles, mais
j'ai du mal à voir le problème avec du code comme celui là (sans
placement new) :

struct C
{
C(double d);
private:
boost::shared_ptr<double> myD;
};

C::C(double d) : myD(new double(d))
{
}


Parce que tu as pris un type trivial, mais remplace double par T
(template class) ou meme std::string, et le probleme est bien la.


Est-ce que tu pourrais donner un exemple, parce que je ne vois pas
(encore) le probleme, a part le fait que si le constructeur de T
lance une exception, elle va se propager a l'exterieur. Est-ce que
c'est ca le niveau de safety, cad le ctor ne provoque pas d'exception ?


Avatar
Loïc Joly

Est-ce que tu pourrais donner un exemple, parce que je ne vois pas
(encore) le probleme, a part le fait que si le constructeur de T
lance une exception, elle va se propager a l'exterieur. Est-ce que
c'est ca le niveau de safety, cad le ctor ne provoque pas d'exception ?


Si on remplace double par string dans mon exemple, alors, le new va
allouer de la mémoire pour la chaîne, puis le constructeur de la chaîne
est appelé (qui fait ses propres allocations mémoire), puis le résultat
est passé au constructeur du shared_ptr qui en prends alors la
possession et le détruira à la destruction de l'objet.

Le problèe est si une exception est lancée au moment de la construction
de la chaîne. Dans ce cas, rien n'a encore été affecté au shard_ptr, qui
ne pourra donc pas faire le ménage, et pourtant on a déjà alloué
manuellement de la mémoire pour la chaîne, qui ne sera jamais libérée.

--
Loïc

Avatar
Jean-Marc Bourguet
Loïc Joly writes:


Est-ce que tu pourrais donner un exemple, parce que je ne vois pas
(encore) le probleme, a part le fait que si le constructeur de T
lance une exception, elle va se propager a l'exterieur. Est-ce que
c'est ca le niveau de safety, cad le ctor ne provoque pas d'exception ?


Si on remplace double par string dans mon exemple, alors, le new va allouer
de la mémoire pour la chaîne, puis le constructeur de la chaîne est appelé
(qui fait ses propres allocations mémoire), puis le résultat est passé au
constructeur du shared_ptr qui en prends alors la possession et le détruira
à la destruction de l'objet.

Le problèe est si une exception est lancée au moment de la construction de
la chaîne. Dans ce cas, rien n'a encore été affecté au shard_ptr, qui ne
pourra donc pas faire le ménage, et pourtant on a déjà alloué manuellement
de la mémoire pour la chaîne, qui ne sera jamais libérée.


Le compilateur doit normalement (*) generer du code qui appelle l'operateur
delete si une exception est lancee pendant l'execution d'un constructeur
appele par une expression new. Dans le cas de tableaux, les elements deja
construits doivent etre detruits.

On parlait du new avec placement, ce cas est le seul cas ou l'operateur
delete avec placement est appele automatiquement.

Je me demande si tu ne confonds pas le cas
f(new X, new Y);
ou un sequencement legal est
new X;
new Y;
constructeur du smart_ptr pour X,
constructeur du smart_ptr pour Y,
appel a f
ou effectivement une exception lancee par le constructeur de Y va liberer
la memoire allouee pour Y mais le X ne sera pas detruit ni sa memoire
liberee.

A+

(*) J'ai le souvenir de cas ou il ne le fait pas mais je ne me souviens
plus des details et n'ai pas le temps de regarder. Ce que j'ai retenu est
qu'en comportement normal (en definissant toujours new et delete qui
correspond), il n'y a pas de problemes.

--
Jean-Marc


1 2 3 4