Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

Warning

71 réponses
Avatar
Sébastien M.
Bonjour,

Cela vous semble-t-il normal que ce code compile normalement, sans
m=EAme un warning ?
(test=E9 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 =3D new B[16];

cout << '\n';
for(int i=3D0; i<16; i++)
{
cout << tab[i].a << ' ';
}
cout << endl;
}

10 réponses

1 2 3 4 5
Avatar
Jean-Marc Bourguet
Sébastien M. 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++/c++-faq-lite/index.html
Site de usenet-fr: http://www.usenet-fr.news.eu.org
Avatar
Grasshoper
07/08/2008 15:46 - Jean-Marc Bourguet :
Sébastien M. 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.
Avatar
Sébastien M.
On 7 août, 15:46, Jean-Marc Bourguet wrote:
Sébastien M. 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égit ime.
Avatar
Jean-Marc Bourguet
Sébastien M. writes:

On 7 août, 15:46, Jean-Marc Bourguet wrote:
> Sébastien M. 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++/c++-faq-lite/index.html
Site de usenet-fr: http://www.usenet-fr.news.eu.org
Avatar
Jean-Marc Bourguet
Grasshoper writes:

07/08/2008 15:46 - Jean-Marc Bourguet :
> Sébastien M. 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++/c++-faq-lite/index.html
Site de usenet-fr: http://www.usenet-fr.news.eu.org
Avatar
Falk Tannhäuser
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
Avatar
Sébastien M.
On 7 août, 15:52, Grasshoper wrote:
07/08/2008 15:46 - Jean-Marc Bourguet :

> Sébastien M. 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
Avatar
Sébastien M.
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 ).
Avatar
Sylvain SF
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.
Avatar
Mickaël Wolff
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
1 2 3 4 5