|
|
|
#1 |
|
Messages: n/a
Hébergeur: |
Bonjour,
Cela vous semble-t-il normal que ce code compile normalement, sans même un warning ? (testé avec gcc 3.4, VS 2003 et VS 2005) #include<iostream> using namespace std; struct A { A() : a(0) {} int a; }; struct B : public A { B() : b(1), c(1), d(1) {} int b,c,d; }; int main() { A* tab = new B[16]; cout << '\n'; for(int i=0; i<16; i++) { cout << tab[i].a << ' '; } cout << endl; } |
|
|
|
#2 |
|
Messages: n/a
Hébergeur: |
Sébastien M. <plouf79@yahoo.fr> writes:
> Cela vous semble-t-il normal que ce code compile normalement, sans > même un warning ? C'est normal que ca compile. On aimerait avoir un warning, mais il demanderait une analyse un peu poussee quand meme. 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++/...ite/index.html Site de usenet-fr: http://www.usenet-fr.news.eu.org |
|
|
|
#3 |
|
Messages: n/a
Hébergeur: |
07/08/2008 15:46 - Jean-Marc Bourguet :
> Sébastien M. <plouf79@yahoo.fr> writes: >> Cela vous semble-t-il normal que ce code compile normalement, sans >> même un warning ? > > C'est normal que ca compile. On aimerait avoir un warning, mais il > demanderait une analyse un peu poussee quand meme. Puis-je naïvement demandé pour quelle raison on pourrait s'attendre à un warning ? S'il vous plaît. |
|
|
|
#4 |
|
Messages: n/a
Hébergeur: |
On 7 août, 15:46, Jean-Marc Bourguet <j...@bourguet.org> wrote:
> Sébastien M. <plou...@yahoo.fr> writes: > > Cela vous semble-t-il normal que ce code compile normalement, sans > > même un warning ? > > C'est normal que ca compile. On aimerait avoir un warning, mais il > demanderait une analyse un peu poussee quand meme. Ca ne me semble a priori pas si poussé que ça : je ne vois beaucoup de cas où A* tab = new B[16]; peut être utilisé de manière légitime. |
|
|
|
#5 |
|
Messages: n/a
Hébergeur: |
Sébastien M. <plouf79@yahoo.fr> writes:
> On 7 août, 15:46, Jean-Marc Bourguet <j...@bourguet.org> wrote: > > Sébastien M. <plou...@yahoo.fr> writes: > > > Cela vous semble-t-il normal que ce code compile normalement, sans > > > même un warning ? > > > > C'est normal que ca compile. On aimerait avoir un warning, mais il > > demanderait une analyse un peu poussee quand meme. > > Ca ne me semble a priori pas si poussé que ça : je ne vois beaucoup de > cas où A* tab = new B[16]; peut être utilisé de manière légitime. Je n'ai pas dis que c'est insurmontable. A partir du moment ou on le desire, c'est possible. Mais a mon avis l'analyse necessaire se trouvera plutot dans des outils specifique (genre QAC++, Coverity) plutot que dans un compilateur car j'ai l'impression qu'elle necessite de maintenir et propager une information qui n'a de raison d'etre que de generer ce warning. (Mais si j'ai deja travaille sur des parseurs, je n'ai jamais travaille sur un compilateur C++). 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++/...ite/index.html Site de usenet-fr: http://www.usenet-fr.news.eu.org |
|
|
|
#6 |
|
Messages: n/a
Hébergeur: |
Grasshoper <grass.hoper@crop.invalid> writes:
> 07/08/2008 15:46 - Jean-Marc Bourguet : > > Sébastien M. <plouf79@yahoo.fr> writes: > >> Cela vous semble-t-il normal que ce code compile normalement, sans > >> même un warning ? > > > > C'est normal que ca compile. On aimerait avoir un warning, mais il > > demanderait une analyse un peu poussee quand meme. > > Puis-je naïvement demandé pour quelle raison on pourrait s'attendre à un > warning ? S'il vous plaît. On peut le desirer (c'est problematique), mais s'y attendre comme je l'ai explique a Sebastien, c'est peut-etre attendre beaucoup d'un compilateur, l'information necessaire n'etant pas la pour d'autres raisons. (Par exemple, un compilateur peut ne donne pas d'indication des variables non initialisees tant qu'on n'a pas activer la passe de l'optimisation qui calcule l'information necessaire sans trop de faux positifs). 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++/...ite/index.html Site de usenet-fr: http://www.usenet-fr.news.eu.org |
|
|
|
#7 |
|
Messages: n/a
Hébergeur: |
Sébastien M. wrote:
> Ca ne me semble a priori pas si poussé que ça : je ne vois beaucoup de > cas où A* tab = new B[16]; peut être utilisé de manière légitime. De toute façon, dans la pratique ce problème ne se produit jamais car depuis tout petit, tout le monde a appris d'utiliser std::vector<B> tab(16); à la place du new[]. :-P Par conséquent, les constructeurs de compilateurs ne se sentent pas pressés pour tenter de détecter le problème à la compilation. De plus, une telle détection me paraît assez difficile à mettre en œuvre dans le cas général où le new B[16] et la conversion de B* vers A* se trouvent dans des fonctions différentes, voir dans des unités de compilation différentes. Falk |
|
|
|
#8 |
|
Messages: n/a
Hébergeur: |
On 7 août, 15:52, Grasshoper <grass.ho...@crop.invalid> wrote:
> 07/08/2008 15:46 - Jean-Marc Bourguet : > > > Sébastien M. <plou...@yahoo.fr> writes: > >> Cela vous semble-t-il normal que ce code compile normalement, sans > >> même un warning ? > > > C'est normal que ca compile. On aimerait avoir un warning, mais il > > demanderait une analyse un peu poussee quand meme. > > Puis-je naïvement demandé pour quelle raison on pourrait s'attendre à un > warning ? S'il vous plaît. C'est un comportement indéfini. Pour les compilateurs avec lesquels j'ai fait les tests, le programme affiche ceci : 0 1 1 1 0 1 1 1 0 1 1 1 0 1 1 1 0 1 1 1 Pourtant on met toujours 0 dans "a" et on demande d'afficher "a" à chaque fois. Naïvement on pourrait s'attendre à avoir ceci : 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -- Sébastien |
|
|
|
#9 |
|
Messages: n/a
Hébergeur: |
On 7 août, 17:18, Falk Tannhäuser <falk.tannhau...@crf.canon.fr>
wrote: > Sébastien M. wrote: > > Ca ne me semble a priori pas si poussé que ça : je ne vois beaucoupde > > cas où A* tab = new B[16]; peut être utilisé de manière légitime. > > De toute façon, dans la pratique ce problème ne se produit jamais car > depuis tout petit, tout le monde a appris d'utiliser > std::vector<B> tab(16); > à la place du new[]. :-P Oui mais malheureusement on doit parfois utiliser des APIs mal faites qui nous obligent à faire ce genre de choses ( new[] à la place de vector ). |
|
|
|
#10 |
|
Messages: n/a
Hébergeur: |
Sébastien M. wrote on 07/08/2008 17:27:
>>> >> Puis-je demander pour quelle raison on pourrait s'attendre à un warning? > > C'est un comportement indéfini. > > Pour les compilateurs avec lesquels j'ai fait les tests, le programme > affiche ceci : > 0 1 1 1 0 1 1 1 0 1 1 1 0 1 1 1 0 1 1 1 car A est un POD de taille "1" (en posant qu'un int à une taille de une unité) et B un POD de 4 unités. le new B[] alloue (et initialise) bien un tableau de POD de taille 4, mais la boucle balaye un A[], en fait on affiche (syntaxe abusive): tab[0].a, tab[0].b, tab[0].c, tab[0].d, tab[1].a, tab[1].b, tab[1].c, tab[1].d, etc l'allocation A* tab = new B[4]; avec la boucle (int i=0; i<16; ++i) donnerait le même résultat et pas d'erreur d'accès hors buffer (or cas d'alignement particulier ou autre "indéfini"). l'opérateur [] appliqué à un tableau ignore tout de la virtualité, son calcul d'offset (comme '++') n'utilise que la taille de son type donc A (soit 1 int). std::vector n'est pas obligeatoire (je n'utilise jamais 'cette' version) mais un tableau doit autant que faire ce peut conserver son type vrai. Sylvain. |
|
|
|
#11 |
|
Messages: n/a
Hébergeur: |
Sylvain SF a écrit :
> l'opérateur [] appliqué à un tableau ignore tout de la virtualité, > son calcul d'offset (comme '++') n'utilise que la taille de son type > donc A (soit 1 int). C'est ce qui explique que, si je rajoute des destructeurs virtuels, un delete [] tab segfault ? -- Mickaël Wolff aka Lupus Michaelis http://lupusmic.org |
|
|
|
#12 |
|
Messages: n/a
Hébergeur: |
Mickaël Wolff wrote on 07/08/2008 22:26:
> Sylvain SF a écrit : >> l'opérateur [] appliqué à un tableau ignore tout de la virtualité, >> son calcul d'offset (comme '++') n'utilise que la taille de son type >> donc A (soit 1 int). > > C'est ce qui explique que, si je rajoute des destructeurs virtuels, un > delete [] tab segfault ? il y a en effet des chances que le delete du second élément mette la cata. (le "iterate_delete_item_from_array" fait un appel virtuel correct, mais le calcul de l'offset de l'élément suivant est mauvais). Sylvain. |
|
|
|
#13 |
|
Messages: n/a
Hébergeur: |
On Thu, 7 Aug 2008 08:38:00 -0700 (PDT), Sébastien M. :
>Oui mais malheureusement on doit parfois utiliser des APIs mal faites >qui nous obligent à faire ce genre de choses ( new[] à la place de >vector ). Uh ? Dans quel cas ? Si tu as une fonction (dans une bibliothèque, typiquement écrite en C) de ce style : int f (char* ptr, size_t lng); tu peux écrire : std::vector <char> buf (la_taille_voulue); f (&buf[0], buf.size()); Il me semble que l'usage de new[] est si rare qu'il justifie, à chaque usage, un commentaire indiquant pourquoi on n'a pas utilisé une autre solution. |
|
|
|
#14 |
|
Messages: n/a
Hébergeur: |
On Aug 7, 9:52 pm, Sylvain SF <sylv...@boiteaspam.info> wrote:
> Sébastien M. wrote on 07/08/2008 17:27: > >> Puis-je demander pour quelle raison on pourrait s'attendre > >> à un warning? > > C'est un comportement indéfini. > > Pour les compilateurs avec lesquels j'ai fait les tests, le > > programme affiche ceci : > > 0 1 1 1 0 1 1 1 0 1 1 1 0 1 1 1 0 1 1 1 > car A est un POD de taille "1" (en posant qu'un int à une > taille de une unité) et B un POD de 4 unités. > le new B[] alloue (et initialise) bien un tableau de POD de > taille 4, mais la boucle balaye un A[], en fait on affiche > (syntaxe abusive): > tab[0].a, tab[0].b, tab[0].c, tab[0].d, tab[1].a, tab[1].b, tab[1].c, > tab[1].d, etc > l'allocation A* tab = new B[4]; avec la boucle (int i=0; i<16; > ++i) donnerait le même résultat et pas d'erreur d'accès hors > buffer (or cas d'alignement particulier ou autre "indéfini"). > l'opérateur [] appliqué à un tableau ignore tout de la > virtualité, son calcul d'offset (comme '++') n'utilise que la > taille de son type donc A (soit 1 int). Ça explique ce qui se passe probablement dans l'implémentation (et c'est en effet la justification du comportement indéfini), mais pour l'utilisateur : l'arithmétique sur pointeurs (et donc l'indexation, qui est définie en termes d'arithmétique sur pointeurs) n'est défini qu'à l'intérieur d'un tableau, avec des pointeurs à des éléments du tableau (ou un au-delà de la fin du tableau). Et que si tu as un tableau de B, un A* ne pourrait jamais désigner un élément du tableau, parce que les éléments ne sont pas des A. > std::vector n'est pas obligeatoire (je n'utilise jamais > 'cette' version) mais un tableau doit autant que faire ce peut > conserver son type vrai. std::vector se comporte plus ou moins comme un tableau classique à cet égard. -- James Kanze (GABI Software) email:james.kanze@gmail.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 |
|
|
|
#15 |
|
Messages: n/a
Hébergeur: |
On Aug 7, 10:26 pm, Mickaël Wolff <mickael.wo...@laposte.net> wrote:
> Sylvain SF a écrit : > > l'opérateur [] appliqué à un tableau ignore tout de la > > virtualité, son calcul d'offset (comme '++') n'utilise que > > la taille de son type donc A (soit 1 int). > C'est ce qui explique que, si je rajoute des destructeurs > virtuels, un delete [] tab segfault ? Surtout, ce qui l'explique, c'est que la norme dit que dans un delete[], si le type dynamique n'est pas le même que le type statique, c'est un comportement indéfini. (Mais la motivation est la même : il a besoin de l'arithmétique sur pointeurs, qui suppose que le compilateur connaissent la taille réele de l'objet.) -- James Kanze (GABI Software) email:james.kanze@gmail.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 |
|
|
|
#16 |
|
Messages: n/a
Hébergeur: |
On Aug 8, 4:46 am, Fabien LE LEZ <grams...@gramster.com> wrote:
> On Thu, 7 Aug 2008 08:38:00 -0700 (PDT), Sébastien M. : [...] > Il me semble que l'usage de new[] est si rare qu'il justifie, > à chaque usage, un commentaire indiquant pourquoi on n'a pas > utilisé une autre solution. Pour confirmer : je pratique le C++ depuis prèsque 20 ans, à tous les niveaux (de l'implémentation des vecteur et des chaînes à l'époque avant la norme, jusqu'aux applications complètes), et je n'ai jamais eu la moindre occasion d'utiliser un new[]. -- James Kanze (GABI Software) email:james.kanze@gmail.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 |
|
|
|
#17 |
|
Messages: n/a
Hébergeur: |
On 8 août, 04:46, Fabien LE LEZ <grams...@gramster.com> wrote:
> On Thu, 7 Aug 2008 08:38:00 -0700 (PDT), Sébastien M. : > > >Oui mais malheureusement on doit parfois utiliser des APIs mal faites > >qui nous obligent à faire ce genre de choses ( new[] à la place de > >vector ). > > Uh ? Dans quel cas ? > Dans cette API, on est sensé hérité d'une classe mère pour ajoutédes comportement. Il y a des donnée 'protected' de la classe mère qui doivent être initialisées par les classes filles dont un tableau d'objet. Cette nouvelle classe doit faire le new sinon la classe mère n'a pas ce quelle veut ... (évidement on n'a pas accès au code de la classe mère) Enfin ... le coté positif c'est que je ne vais bientôt plus travailler sur ce truc :-D -- Sébastien |
|
|
|
#18 |
|
Messages: n/a
Hébergeur: |
> > Pour confirmer : je pratique le C++ depuis prèsque 20 ans, à > tous les niveaux (de l'implémentation des vecteur et des chaînes > à l'époque avant la norme, jusqu'aux applications complètes), et > je n'ai jamais eu la moindre occasion d'utiliser un new[]. > Sauf si on utilise un "allocator" développé par quelqu'un d'autre je pense qu'on doit avoir au moins un new dans le programme si on implémente soit même les classes de base :-D Après je suis d'accord qu'on ne doit pas avoir de "new" si on utilise la STL et pas plus d'un "new" si on implémente tout depuis le début. -- Sébastien |
|
|
|
#19 |
|
Messages: n/a
Hébergeur: |
On Fri, 8 Aug 2008 02:16:59 -0700 (PDT), Sébastien M.
<plouf79@yahoo.fr>: >Dans cette API, on est sensé hérité d'une classe mère pour ajouté des Par pitié, relis ta prose avant de poster ! >Il y a des donnée 'protected' de la classe mère qui doivent être >initialisées par les classes filles dont un tableau d'objet. Gnii ? J'ai l'impression que c'est un bon candidat pour <http://thedailywtf.com/> :-/ >Enfin ... le coté positif c'est que je ne vais bientôt plus travailler >sur ce truc :-D J'imagine que ça va beaucoup te soulager. |
|
|
|
#20 |
|
Messages: n/a
Hébergeur: |
> >Dans cette API, on est sensé hérité d'une classe mère pour ajouté des > > Par pitié, relis ta prose avant de poster ! oups :-( désolé. > >Il y a des donnée 'protected' de la classe mère qui doivent être > >initialisées par les classes filles dont un tableau d'objet. > > Gnii ? J'ai l'impression que c'est un bon candidat pour > <http://thedailywtf.com/> :-/ oui, je pense qu'on pourrait même faire une série d'articles. > >Enfin ... le coté positif c'est que je ne vais bientôt plus travailler > >sur ce truc :-D > > J'imagine que ça va beaucoup te soulager. oh oui. |
|
|
|
#21 |
|
Messages: n/a
Hébergeur: |
Sébastien M. <plouf79@yahoo.fr> writes:
> > > > Pour confirmer : je pratique le C++ depuis prèsque 20 ans, à > > tous les niveaux (de l'implémentation des vecteur et des chaînes > > à l'époque avant la norme, jusqu'aux applications complètes), et > > je n'ai jamais eu la moindre occasion d'utiliser un new[]. > > > > Sauf si on utilise un "allocator" développé par quelqu'un d'autre je > pense qu'on doit avoir au moins un new dans le programme si on > implémente soit même les classes de base :-D Il a ecrit new[] pas new. (Je dois en avoir ecrit mais je ne me souviens pas d'occasions ou vector<> ou une classe similaire n'aurait pas ete en fait une meilleure solution). 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++/...ite/index.html Site de usenet-fr: http://www.usenet-fr.news.eu.org |
|
|
|
#22 |
|
Messages: n/a
Hébergeur: |
> Il a ecrit new[] pas new. Il est temps que je parte en vacances, je me met à raconter n'importe quoi et à lire de travers. > (Je dois en avoir ecrit mais je ne me souviens pas d'occasions ou vector<> > ou une classe similaire n'aurait pas ete en fait une meilleure solution). C'est vrai qu'à part celui que j'ai du faire il y a quelques jours contraint et forcé par l'API qu'on utilise, je ne me souviens pas d'avoir utilisé new[] sauf peut-être dans mes premiers programmes en c+ +. |
|
|
|
#23 |
|
Messages: n/a
Hébergeur: |
On Aug 8, 11:50 am, Sébastien M. <plou...@yahoo.fr> wrote:
> > Pour confirmer : je pratique le C++ depuis prèsque 20 ans, à > > tous les niveaux (de l'implémentation des vecteur et des chaînes > > à l'époque avant la norme, jusqu'aux applications complètes), et > > je n'ai jamais eu la moindre occasion d'utiliser un new[]. > Sauf si on utilise un "allocator" développé par quelqu'un d'autre je > pense qu'on doit avoir au moins un new dans le programme si on > implémente soit même les classes de base :-D Évidemment qu'il y a des new, beaucoup même. Mais pas de new[]. > Après je suis d'accord qu'on ne doit pas avoir de "new" si on > utilise la STL et pas plus d'un "new" si on implémente tout > depuis le début. Même sans la STL (qui n'existait pas quand j'ai commencé le C++), je ne vois pas une utilisation pour new[]. Si tu n'as pas la STL, la première chose, c'est d'en implémenter quelque chose de plus ou moins semblable. Moins complet, évidemment, mais souvent mieux conçu ou plus adapté à tes besoins. -- James Kanze (GABI Software) email:james.kanze@gmail.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 |
|
|
|
#24 |
|
Messages: n/a
Hébergeur: |
On Aug 8, 11:16 am, Sébastien M. <plou...@yahoo.fr> wrote:
> On 8 août, 04:46, Fabien LE LEZ <grams...@gramster.com> wrote: > > On Thu, 7 Aug 2008 08:38:00 -0700 (PDT), Sébastien M. : > > >Oui mais malheureusement on doit parfois utiliser des APIs > > >mal faites qui nous obligent à faire ce genre de choses ( > > >new[] à la place de vector ). > > Uh ? Dans quel cas ? > Dans cette API, on est sensé hérité d'une classe mère pour > ajouté des comportement. > Il y a des donnée 'protected' de la classe mère qui doivent > être initialisées par les classes filles dont un tableau > d'objet. Cette nouvelle classe doit faire le new sinon la > classe mère n'a pas ce quelle veut ... (évidement on n'a pas > accès au code de la classe mère) Et &v[0] d'un vector convenablement dimensionné ne ferait-il pas l'affaire ? (Ou est-ce que la classe mère ferait elle-même le delete[] ?) (Je n'ai jamais eu à le faire, mais l'implémentation de strstreambuf doit bien exiger un new[]. Puisque il garantit que le client peut faire un delete[] sur le pointeur renvoyé par str(); c'est donc difficile de faire autrement.) -- James Kanze (GABI Software) email:james.kanze@gmail.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 |
|
|
|
#25 |
|
Messages: n/a
Hébergeur: |
> > Dans cette API, on est sensé hérité d'une classe mère pour > > ajouté des comportement. > > Il y a des donnée 'protected' de la classe mère qui doivent > > être initialisées par les classes filles dont un tableau > > d'objet. Cette nouvelle classe doit faire le new sinon la > > classe mère n'a pas ce quelle veut ... (évidement on n'a pas > > accès au code de la classe mère) > > Et &v[0] d'un vector convenablement dimensionné ne ferait-il pas > l'affaire ? (Ou est-ce que la classe mère ferait elle-même le > delete[] ?) > C'est en effet la classe mère qui fait le delete[]. |
|
![]() |
| Outils de la discussion | |
|
|