Warning

Le
Sébastien M.
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 << '';
for(int i=0; i<16; i++)
{
cout << tab[i].a << ' ';
}
cout << endl;
}
Vidéos High-Tech et Jeu Vidéo
Téléchargements
Vos réponses Page 1 / 8
Gagnez chaque mois un abonnement Premium avec GNT : Inscrivez-vous !
Trier par : date / pertinence
Jean-Marc Bourguet
Le #16496291
Sébastien M.
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++/c++-faq-lite/index.html
Site de usenet-fr: http://www.usenet-fr.news.eu.org
Grasshoper
Le #16496281
07/08/2008 15:46 - Jean-Marc Bourguet :
Sébastien M.
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.
Sébastien M.
Le #16496491
On 7 août, 15:46, Jean-Marc Bourguet
Sébastien M. > 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égit ime.
Jean-Marc Bourguet
Le #16496691
Sébastien M.
On 7 août, 15:46, Jean-Marc Bourguet > Sébastien M. > > 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++/c++-faq-lite/index.html
Site de usenet-fr: http://www.usenet-fr.news.eu.org
Jean-Marc Bourguet
Le #16496851
Grasshoper
07/08/2008 15:46 - Jean-Marc Bourguet :
> Sébastien M. >> 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++/c++-faq-lite/index.html
Site de usenet-fr: http://www.usenet-fr.news.eu.org
Falk Tannhäuser
Le #16497231
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
Sébastien M.
Le #16497461
On 7 août, 15:52, Grasshoper
07/08/2008 15:46 - Jean-Marc Bourguet :

> Sébastien M. >> 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
Sébastien M.
Le #16497731
On 7 août, 17:18, Falk Tannhäuser wrote:
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



Oui mais malheureusement on doit parfois utiliser des APIs mal faites
qui nous obligent à faire ce genre de choses ( new[] à la place de
vector ).
Sylvain SF
Le #16499921
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.
Mickaël Wolff
Le #16500151
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
Publicité
Poster une réponse
Anonyme