Il linguaggio C++
 

Strano comportamento del compilatore (VC 2008, VC2010)

Angelo Paolitto 27 Mag 2015 14:13
Scrivendo un pezzo di codice mi sono imbattuto in quello che
a me sembra un bug dei compilatori in oggetto.

Ho un progetto dove per errore ho dichiarato due strutture
diverse, in due ******* diversi, chiamandole con lo stesso nome.

il codice di sotto compila senza battere ciglio (con W4 turned on)
salvo scoppiare su una delle due delete.

E' normale che un compilatore non segnali un problema del genere?

decl_1.cpp
----------
#include <string>

typedef struct {

int testInt;
std::string testString;
} testDecl;

int callTestDecl_1(void)
{
int retVal = 0;

testDecl* ptrP = new testDecl[2];

delete [] ptrP;

return retVal;
}

decl_2.cpp
----------
#include <string>
#include <vector>

typedef struct {

int testInt;
std::vector<std::string> testVect;
} testDecl;

int callTestDecl_2(void)
{
int retVal = 0;

testDecl* ptrP = new testDecl[5];

delete [] ptrP;

return retVal;
}

mainDecl.cpp
------------
int callTestDecl_1(void);
int callTestDecl_2(void);

int main(void)
{
callTestDecl_1();
callTestDecl_2();

return 0;
}

C:\>iao Angelo
enoquick 27 Mag 2015 14:39
Il 27/05/2015 07:13, Angelo Paolitto ha scritto:
> Scrivendo un pezzo di codice mi sono imbattuto in quello che
> a me sembra un bug dei compilatori in oggetto.
>
> Ho un progetto dove per errore ho dichiarato due strutture
> diverse, in due ******* diversi, chiamandole con lo stesso nome.
>
> il codice di sotto compila senza battere ciglio (con W4 turned on)
> salvo scoppiare su una delle due delete.
>
> E' normale che un compilatore non segnali un problema del genere?
>
> decl_1.cpp
> ----------
> #include <string>
>
> typedef struct {
>
> int testInt;
> std::string testString;
> } testDecl;
>
> int callTestDecl_1(void)
> {
> int retVal = 0;
>
> testDecl* ptrP = new testDecl[2];
>
> delete [] ptrP;
>
> return retVal;
> }
>
> decl_2.cpp
> ----------
> #include <string>
> #include <vector>
>
> typedef struct {
>
> int testInt;
> std::vector<std::string> testVect;
> } testDecl;
>
> int callTestDecl_2(void)
> {
> int retVal = 0;
>
> testDecl* ptrP = new testDecl[5];
>
> delete [] ptrP;
>
> return retVal;
> }
>
> mainDecl.cpp
> ------------
> int callTestDecl_1(void);
> int callTestDecl_2(void);
>
> int main(void)
> {
> callTestDecl_1();
> callTestDecl_2();
>
> return 0;
> }
>
> C:\>iao Angelo
>




Questo è il paragrafo 15.2 di 'The C++ programming language, 4 edition:

15.2 Linkage
Names of functions, classes, templates, variables, namespaces,
enumerations, and enumerators
must be used consistently across all translation units unless they are
explicitly specified to be local.
It is the programmer’s task to ensure that every namespace, class,
function, etc., is properly
declared in every translation unit in which it appears and that all
declarations referring to the same
entity are consistent.
Jack 27 Mag 2015 15:09
Angelo Paolitto <angelo.paolitto@tiscalinet.it> wrote:

> Scrivendo un pezzo di codice mi sono imbattuto in quello che
> a me sembra un bug dei compilatori in oggetto.
>
> Ho un progetto dove per errore ho dichiarato due strutture
> diverse, in due ******* diversi, chiamandole con lo stesso nome.
>
> il codice di sotto compila senza battere ciglio (con W4 turned on)
> salvo scoppiare su una delle due delete.

quale dei due delete?

> E' normale che un compilatore non segnali un problema del genere?

il compilatore C (e C++) si aspetta che tu sappia quallo che stai
facendo, quindi controlla solo la sintassi.
Se la sintassi e' giusta, per il compilatore va tutto bene.

Ciao Jack

--
Yoda of Borg am I! Assimilated shall you be! Futile resistance is, hmm?
enoquick 27 Mag 2015 15:30
Il 27/05/2015 08:09, Jack ha scritto:
> Angelo Paolitto <angelo.paolitto@tiscalinet.it> wrote:
>
> il compilatore C (e C++) si aspetta che tu sappia quallo che stai
> facendo, quindi controlla solo la sintassi.
> Se la sintassi e' giusta, per il compilatore va tutto bene.
>


Per il compilatore puo anche andare tutto bene , in fondo compila un
modulo indipendentemente da altri moduli
Peccato che questo non puo garantire il funzionamento di un programma
Questo perchè deve interviene anche un altro oggetto nel processo di
produzione dell' eseguibile e si chiama linker
Jack 27 Mag 2015 15:49
enoquick <enoquick@gmail.com> wrote:

> Il 27/05/2015 08:09, Jack ha scritto:
>> Angelo Paolitto <angelo.paolitto@tiscalinet.it> wrote:
>>
>> il compilatore C (e C++) si aspetta che tu sappia quallo che stai
>> facendo, quindi controlla solo la sintassi.
>> Se la sintassi e' giusta, per il compilatore va tutto bene.
>>
>
>
> Per il compilatore puo anche andare tutto bene , in fondo compila un
> modulo indipendentemente da altri moduli
> Peccato che questo non puo garantire il funzionamento di un programma
> Questo perchè deve interviene anche un altro oggetto nel processo di
> produzione dell' eseguibile e si chiama linker

si ma se ci sono due oggetti diversi, con lo stesso nome che cozzano da
qualche parte il compilatore e/o il linker si accorge e in genere lo
dice.
Visto che nell'esempio dell'op i due oggetti sono in files diversi,
vengono usati in funzioni diverse e non interagiscono mai, per il
compilatore/linker non ci sono problemi.
IMHO il problema va cercato altrove.

Ciao Jack
--
Yoda of Borg am I! Assimilated shall you be! Futile resistance is, hmm?
enoquick 27 Mag 2015 16:06
Il 27/05/2015 08:49, Jack ha scritto:
> enoquick <enoquick@gmail.com> wrote:
>
>> Il 27/05/2015 08:09, Jack ha scritto:
>>> Angelo Paolitto <angelo.paolitto@tiscalinet.it> wrote:
>>>
>>> il compilatore C (e C++) si aspetta che tu sappia quallo che stai
>>> facendo, quindi controlla solo la sintassi.
>>> Se la sintassi e' giusta, per il compilatore va tutto bene.
>>>
>>
>>
>> Per il compilatore puo anche andare tutto bene , in fondo compila un
>> modulo indipendentemente da altri moduli
>> Peccato che questo non puo garantire il funzionamento di un programma
>> Questo perchè deve interviene anche un altro oggetto nel processo di
>> produzione dell' eseguibile e si chiama linker
>
> si ma se ci sono due oggetti diversi, con lo stesso nome che cozzano da
> qualche parte il compilatore e/o il linker si accorge e in genere lo
> dice.
> Visto che nell'esempio dell'op i due oggetti sono in files diversi,
> vengono usati in funzioni diverse e non interagiscono mai, per il
> compilatore/linker non ci sono problemi.
> IMHO il problema va cercato altrove.
>
> Ciao Jack
>


Ho postato in un altro thread quello che c'è scritto nello Stroutput,
sezione 15.2
Non la pensa cosi
Jack 27 Mag 2015 16:41
enoquick <enoquick@gmail.com> wrote:

> Ho postato in un altro thread quello che c'è scritto nello Stroutput,
> sezione 15.2
> Non la pensa cosi

la parola chiave, in quello che hai postato, e' "translation unit".

Ciao Jack
--
Yoda of Borg am I! Assimilated shall you be! Futile resistance is, hmm?
enoquick 27 Mag 2015 17:12
Il 27/05/2015 09:41, Jack ha scritto:
> enoquick <enoquick@gmail.com> wrote:
>
>> Ho postato in un altro thread quello che c'è scritto nello Stroutput,
>> sezione 15.2
>> Non la pensa cosi
>
> la parola chiave, in quello che hai postato, e' "translation unit".
>
> Ciao Jack
>

Quello che ho chiamato modulo, ma non capisco dove vuoi arrivare
Jack 27 Mag 2015 19:52
enoquick <enoquick@gmail.com> wrote:

> Il 27/05/2015 09:41, Jack ha scritto:
>> enoquick <enoquick@gmail.com> wrote:
>>
>>> Ho postato in un altro thread quello che c'è scritto nello Stroutput,
>>> sezione 15.2
>>> Non la pensa cosi
>>
>> la parola chiave, in quello che hai postato, e' "translation unit".
>>
>> Ciao Jack
>>
>
> Quello che ho chiamato modulo, ma non capisco dove vuoi arrivare

che i due files, dove l'op ha messo le due strutture che ha chiamato
nello stesso modo, sono due translation unit diverse, e quindi il
compilatore/linker non ha problemi a gestirle.
Il problema dell'op e' altrove.

Ciao Jack
--
Yoda of Borg am I! Assimilated shall you be! Futile resistance is, hmm?
enoquick 27 Mag 2015 19:58
Il 27/05/2015 12:52, Jack ha scritto:
> enoquick <enoquick@gmail.com> wrote:
>
>> Il 27/05/2015 09:41, Jack ha scritto:
>>> enoquick <enoquick@gmail.com> wrote:
>>>
>>>> Ho postato in un altro thread quello che c'è scritto nello Stroutput,
>>>> sezione 15.2
>>>> Non la pensa cosi
>>>
>>> la parola chiave, in quello che hai postato, e' "translation unit".
>>>
>>> Ciao Jack
>>>
>>
>> Quello che ho chiamato modulo, ma non capisco dove vuoi arrivare
>
> che i due files, dove l'op ha messo le due strutture che ha chiamato
> nello stesso modo, sono due translation unit diverse, e quindi il
> compilatore/linker non ha problemi a gestirle.
> Il problema dell'op e' altrove.
>
> Ciao Jack
>
Names of functions, classes, templates, variables, namespaces,
enumerations, and enumerators
must be used consistently across all translation units unless they are
explicitly specified to be local

Che significa secondo te ?
Massimo Soricetti 30 Mag 2015 01:40
On 27/05/2015 19:58, enoquick wrote:
>
> Che significa secondo te ?

Che quello che ha scritto Angelo va bene, per quanto riguarda le due
struct. Sono dichiarate in due ******* .c diversi e non si fa riferimento a
loro da fuori: sono dati locali e non c'è problema se si chiamano con lo
stesso nome. Il baco è altrove.
enoquick 30 Mag 2015 06:02
Il 29/05/2015 18:40, Massimo Soricetti ha scritto:
> On 27/05/2015 19:58, enoquick wrote:
>>
>> Che significa secondo te ?
>
> Che quello che ha scritto Angelo va bene, per quanto riguarda le due
> struct. Sono dichiarate in due ******* .c diversi e non si fa riferimento a
> loro da fuori: sono dati locali e non c'è problema se si chiamano con lo
> stesso nome. Il baco è altrove.
>

Basta provare a cambiare nome ad una delle due struct e vedere se funziona
enoquick 30 Mag 2015 15:30
Il 29/05/2015 23:02, enoquick ha scritto:
> Il 29/05/2015 18:40, Massimo Soricetti ha scritto:
>> On 27/05/2015 19:58, enoquick wrote:
>>>
>>> Che significa secondo te ?
>>
>> Che quello che ha scritto Angelo va bene, per quanto riguarda le due
>> struct. Sono dichiarate in due ******* .c diversi e non si fa riferimento a
>> loro da fuori: sono dati locali e non c'è problema se si chiamano con lo
>> stesso nome. Il baco è altrove.
>>
>
> Basta provare a cambiare nome ad una delle due struct e vedere se funziona
>

per sfizio ho fatto un paio di prove

Sotto g++ funziona,nessun problema
In visual stu***** 2010 ho fatto un paio di provette
In pratica vengono chiamati i costruttori e distruttori sbagliati per
uno dei due
Avendo lo stesso nome il linker non capisce bene (ma non so perchè) e l'
heap viene corrotto causando il crash
Ma non è un baco, è quella che viene chiamata 'undefined behaviour' per
via di questa:

15.2 Linkage
Names of functions, classes, templates, variables, namespaces,
enumerations, and enumerators
must be used consistently across all translation units unless they are
explicitly specified to be local.
It is the programmer’s task to ensure that every namespace, class,
function, etc., is properly
declared in every translation unit in which it appears and that all
declarations referring to the same
entity are consistent.


La spiegazione l' ho data, se qualcuno ha una spiegazione migliore si
accomodi
Angelo Paolitto 8 Giu 2015 13:57
On Saturday, May 30, 2015 at 3:30:45 PM UTC+2, enoquick wrote:

>
> per sfizio ho fatto un paio di prove
>
> Sotto g++ funziona,nessun problema
> In visual stu***** 2010 ho fatto un paio di provette
> In pratica vengono chiamati i costruttori e distruttori sbagliati per
> uno dei due
> Avendo lo stesso nome il linker non capisce bene (ma non so perchè) e l'
> heap viene corrotto causando il crash
> Ma non è un baco, è quella che viene chiamata 'undefined behaviour' per
> via di questa:
>
> 15.2 Linkage
> Names of functions, classes, templates, variables, namespaces,
> enumerations, and enumerators

Secondo me il problema non e' di linkage, ma di scope. Ho dichiarato due
nomi uguali nello scope globale e questi sono visti in tutto il programma
e non (come credevo erroneamente) nella translation unit: visto che le
dichiarazioni sono diverse VC fa un po' quello che ******* vuole in fase di
linking.

Ho fatto una fesseria. :-)

C:\>iao Angelo
enoquick 8 Giu 2015 14:33
Il 08/06/2015 06:57, Angelo Paolitto ha scritto:
> On Saturday, May 30, 2015 at 3:30:45 PM UTC+2, enoquick wrote:
>
>>
>> per sfizio ho fatto un paio di prove
>>
>> Sotto g++ funziona,nessun problema
>> In visual stu***** 2010 ho fatto un paio di provette
>> In pratica vengono chiamati i costruttori e distruttori sbagliati per
>> uno dei due
>> Avendo lo stesso nome il linker non capisce bene (ma non so perchè) e l'
>> heap viene corrotto causando il crash
>> Ma non è un baco, è quella che viene chiamata 'undefined behaviour' per
>> via di questa:
>>
>> 15.2 Linkage
>> Names of functions, classes, templates, variables, namespaces,
>> enumerations, and enumerators
>
> Secondo me il problema non e' di linkage, ma di scope. Ho dichiarato due
> nomi uguali nello scope globale e questi sono visti in tutto il programma
> e non (come credevo erroneamente) nella translation unit: visto che le
> dichiarazioni sono diverse VC fa un po' quello che ******* vuole in fase di
> linking.
>



Il problema deve stare per forza nella fase di linkage
Quando si compila un ******* per il compilatore non esiste correlazione
con altri *******

g++ -c ******* .cpp
g++ -c ******* .cpp


Quando si compila ******* .cpp il compilatore non sa nulla di ******* .cpp e
viceversa

g++ -o exe ******* .o ******* .o

Ma quando si produce exe subentra il linker
Non penso proprio che in vc++ sia diverso

Chiaramente il problema sussiste in quanto le due definizioni di
strutture sone nello stesso scope e con struttura interna differente
Se fossero state dichiarate con lo stesso nome ma in diversi scope il
problema non sussisterebbe:

namespace A { struct x {...}}
namespace B { struct x {...}}

questa è corretta, in fondo una si chiama A::x e l' altra B::x


Ma comunque,come avevo già scritto,non è un baco di vc++ ma un caso di
undefined behaviour

> Ho fatto una fesseria. :-)
>


Hai fatto una fesseria in quanto non è cosi che si scrive sw in C++ (ma
anche in C)
Si usano gli header per le dichiarazioni e definizioni di struct a meno
di non volerlo farle in modo privato (locali ad una unita di traduzione)

namespace { struct x{..}}

usando i namespace anonimi
angelo.paolitto@tiscalinet.it 8 Giu 2015 16:19
On Monday, June 8, 2015 at 2:33:44 PM UTC+2, enoquick wrote:


>
> Hai fatto una fesseria in quanto non è cosi che si scrive sw in C++ (ma
> anche in C)

A volte mi capita di essere "creativo", mi sembrava un buon modo
per evitare di sprememrmi troppo le meningi su come chiamare delle
strutture che venivano usate solo all'interno del ******* in cui erano
definite.

Avevo gia' risolto aggiungendo il prefisso del nome della dialog che
utilizza la struttura.

C:\>iao Angelo
enoquick 8 Giu 2015 16:41
Il 08/06/2015 09:19, angelo.paolitto@tiscalinet.it ha scritto:
> On Monday, June 8, 2015 at 2:33:44 PM UTC+2, enoquick wrote:
>
>
>>
>> Hai fatto una fesseria in quanto non è cosi che si scrive sw in C++ (ma
>> anche in C)
>
> A volte mi capita di essere "creativo", mi sembrava un buon modo
> per evitare di sprememrmi troppo le meningi su come chiamare delle
> strutture che venivano usate solo all'interno del ******* in cui erano
> definite.
>
> Avevo gia' risolto aggiungendo il prefisso del nome della dialog che
> utilizza la struttura.
>
> C:\>iao Angelo
>

Come ho gia scritto,se vuoi le strutture private usa i namespace anonimi

Links
Giochi online
Dizionario sinonimi
Leggi e codici
Ricette
Testi
Webmatica
Hosting gratis
   
 

Il linguaggio C++ | Tutti i gruppi | it.comp.lang.c++ | Notizie e discussioni lang cpp | Lang cpp Mobile | Servizio di consultazione news.