Newsgroup: it.comp.lang.c++
Titolo: Strano comportamento del compilatore (VC 2008, VC2010)

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 file 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.
 
 
 
 
 
 
 
 

 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?


 
 
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.


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

 Non la pensa cosi
 
la parola chiave, in quello che hai postato, e' "translation unit".



 
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.



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 ?
 
 

 Che significa secondo te ?
 
Che quello che ha scritto Angelo va bene, per quanto riguarda le due
struct. Sono dichiarate in due file .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 studio 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
 
 
 

 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 cazzo vuole in fase di
linking.
 
Ho fatto una fesseria. :-)
 
C:\>iao Angelo


Il problema deve stare per forza nella fase di linkage
Quando si compila un  file per il compilatore non esiste correlazione 
con altri file
 
 
g++ -c file1.cpp
g++ -c file2.cpp
 
 
Quando si compila file1.cpp il compilatore non sa nulla di file2.cpp e 
viceversa
 
g++ -o exe file1.o file2.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
 
 
 
 
 
 
 
 

 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 file 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