Newsgroup: it.comp.lang.c++
Titolo: Strani comportamenti?

Dopo tremende ore di debug mi sono accorto che quando dichiaro
int matrXmin[600]=new int(600);
int matrXmax[600]=new int(600);
le due matrici hanno allocato aree di memoria sovrapposte.
C'è un motivo perchè accade ciò?
Altro problemino:
struct chunck{
  float id;
  int len;
}
il compilatore restituisce 8: sizeof(chunck)
il compilatore restituisce 6: sizeof(id)+sizeof(len)
scusate se non ho guardato nei post precedenti ma credo non sia
necessario. Sono convinto che le leggi della meccanica quantistica
cospirino contro di me. Il compilatore è quello del borland C++ 5.

> il compilatore restituisce 6: sizeof(id)+sizeof(len)
naturalmente era:sizeof(float)+sizeof(int)

 C'è un motivo perchè accade ciò?
No. C'e' sicuramente un qualche altro errore molto piu' subdulo che fai in
seguito...
Puoi scoprirlo facilmente: ferma il debug dopo l'allocazione e guarda i valori
dei puntatori... e cosi' vedi se sono indirizzi che si sovrappongono (basta
tenere presente che new int(600) alloca un tot di byte (presumibilmente 4 *
600 se non dico c@**@te).
E comunque non capisco l'utilita' di quel codice. Basta scrivere
int matrXmin[600];
int matrXmax[600];
Per ottenere quello che vuoi... o sbaglio?
ciao
-- 
Marco Ermini
http://miselastra.org
 - ICQ UIN 50825709 - GPG KEY 0x64ABF7C6
Perche' perdere tempo ad imparare quando l'ignoranza e' istantanea? (Hobbes)

 }
ops ... non ci badate. lo riscrivo:
 struct chunck{
   short id;
   int len;
 }
 
il compilatore restituisce 8: sizeof(chunck)
il compilatore restituisce 6: sizeof(short)+sizeof(int)

 int matrXmax[600];
 
per il momento infatti ho risolto cosě, e non da problemi. 
Quindi non č dovuto a errori che faccio in seguito.
Ma in questo modo alloco una matrice statica!!!
Sul fatto che il compilatore mi alloca memoria sovrapposta non vi č alcun 
dubbio.

 dubbio.
Io direi invece che l'unico dubbio che non ho e' che hai utilizzato una
sintassi quanto meno strana e poco usuale, IMHO assai poco pulita e poco
consona ad una programmazione efficace. In effetti dalla tua sintassi puo'
uscire di tutto. Urge ripasso sul libro di C++ ;-)




Posta tutto il pezzo di programma che restituisce questa cosa e facci vedere
come fai *esattamente*. Fai un piccolo main che fa solo questo, eseguilo,
dicci cosa restituisce, e posta il sorgente. Visto il tuo codice precedente ho
meno dubbi sul compilatore che su quello che fai tu (senza offesa eh!! ;-)))


ti prego di non infierire. Sono fuso. stanotte non ho dormito.
Hai perfettamente ragione, il codice era questo:
int *matrXmin=new int(600);
int *matrXmax=new int(600);
Il post non avevo avuto modo di cancellarlo.

 Il post non avevo avuto modo di cancellarlo.
Io farei molto banalmente
int *matrXmin = (int *)malloc (sizeof (int) * 600);
Inoltre, non ha senso fare new su un tipo semplice. Il C++ non e' lo
Smalltalk, i tipi semplici non sono classi, quindi la keyword new() sul tipo
int non ha alcun senso. new() e destroy() hanno senso solo su classi, che
quindi hanno un costruttore ed un distruttore.
Per fare quello che vuoi fare tu, allocare una matrice dinamicamente con new()
e deallocarla con destroy(), devi implementare una classe matrice ed operare
su quella (oppure molto piu' proficuamente utilizzare quella gia' fatta nelle
STL).


ecco tutto il codice:
//file: main.c++
struct chunck{
    	short id;
    	int len;
};
int main(int argc, char* argv[])
{
	int ris1=sizeof(chunck);
      int ris2=sizeof(short)+sizeof(int);
	return 0;
}
//fine
l'ho provato anche con il visual c++ 6.
Per ogni elemento short nella struct, la dimenzione aumenta di 4.

> int *matrXmax=new int(600);
ma guarda!!!
un errore scemo come questo che nottata mi ha fatto passare.
Dico io non me ne accorgo neanche dopo che le guardo per 10 ore di fila che 
quelle sono parentesi tonde e non quadrate?
cosě non va. Mi devo prendere una vacanza!!!
by

 Per ogni elemento short nella struct, la dimenzione aumenta di 4.prova1.c: 
Alza il livello di warning del tuo compilatore. Sul mio, il tuo codice (che
ancora una volta non ha alcun senso) non compila affatto, e mi dice:
In function `main':
prova.c:8: `chunck' undeclared (first use in this function)
prova.c:8: (Each undeclared identifier is reported only once
prova.c:8: for each function it appears in.)
(Linux + gcc).
Quello che tu volevi realmente fare e' questo:
struct chunck{
        short id;
        int len;
} chunck_obj;
int main(int argc, char* argv[])
{
        int ris1=sizeof(chunck_obj);
        int ris2=sizeof(short)+sizeof(int);
        printf ("%d, %d", ris1, ris2);
        return 0;
}
Riesci a cogliere la differenza con quello che hai scritto tu? sai la
differenza tra una classe (tipo formale, che esiste solo come dichiarazione e
non in memoria) e l'istanza di una classe (oggetto concreto presente in
memoria)? se non la sai, non hai studiato abbastanza ;-)


 così non va. Mi devo prendere una vacanza!!!
Al di la' delle parentesi tonde o quadrate, cerca di seguire il mio consiglio
se puoi.


 concreto presente in memoria)? 
e allora dimmi:
short non è una istanza. sizeof(short)=2
long non è una istanza.  sizeof(int)=4
ma sizeof mi ha dato per entrambi la dimenzione che mi aspettavo.
Come vedi il codice che ti ho inviato serve solo per un debugger. 
Chi ci bada a questi warning, in questo caso.
Io mi aspetto che la classe chunck abbia dimenzione 6. Invece no. Ha 
dimenzione 8 e non so il motivo.
L'oggetto chunck_obj comunque ha pure dimenzione di 8.

 L'oggetto chunck_obj comunque ha pure dimenzione di 8.
La "dimenZione" (in italiano si dice dimensione!!!) a te non deve interessare
piu' di tanto. Tu non devi usare dimensioni hardcoded: sizeof() c'e' apposta.
Se a lui servono 8 byte, ad un altro compilatore o su un'altra piattaforma
gliene possono servire 16, come puo' darsi che faccia un padding perche' hai
definito di default una qualche #PRAGMA PAD STRUCT 8 o menate del genere che
tu nemmeno sai; tu devi scrivere codice portabile. Se vuoi sapere la rava e la
fava di come funziona un compilatore, leggi nella sua documentazione, ma dal
punto di vista della programmazione, nel momento in cui sei concentrato a
realizzare una certa funzionalita', ti interessa certamente, ma solo fino ad
un certo punto.


non ho tempo da perdere con le speculazioni, oggi.
In C++, sizeof riporta in ogni caso la dimenzione dell'oggetto anche se gli 
dai una classe come parametro. Almeno questo è scritto nella documentazione 
della borland.
Evitando speculazioni, e andando sul pratico, tu mi sai dire perchè la 
seguente struct ha dimensione 20?
struct chunck{
    	short id1;
 	short id2;
    	short id3;
    	short id4;
    	int len;
}obj;
anzi:
mi sai dire perchè obj ha dimensione 20?
da notare che sizeof(obj.id1) e sizeof(short) restituiscono entrambe 2.

 seguente struct ha dimensione 20?
[...]
Che cosa te ne frega? Se non hai tempo per le speculazioni, sbattitene alla
grande del perche' e programma!


mi sai dire perchč obj ha dimensione 20?
VC++ (e anche altri compilatori) allineano ogni singolo
membro di una struttura al prossimo multiplo di 32 bit.
Il motivo e' che nei processori intel recenti accedere
alla memoria non allineata alla fullword comporta delle
non trascurabili penalita' di prestazioni.
Nota che lo standard dice semplicemente che la dimensione
di una struttura e' *MAGGIORE O UGUALE* alla somma delle
dimensioni dei membri. Ci sono architetture in cui non si
tratta solo di problemi di prestazioni, ma accedere ad
elementi non allineati (es un double grande 8 byte che
non sia ad un indirizzo multiplo di 8) e' vietato e
comporta il blocco del programma.
Negli ambienti in cui si tratta semplicemente di una
penalizzazione ci sono spesso delle opzioni di "packing"
in cui si chiede al compilatore di modificare queste regole
di allineamento. Su VC++ esiste la #pragma chiamata "pack".
Nota anche che nel caso dell'array le cose sono diverse:
in particolare lo standard garantisce che il sizeof di
un array di N elementi e' esattamente N volte il sizeof
del singolo elemento dell'array.
HTH
Andrea

600 se non dico c@**@te).
L'espressione "new int(600)" alloca *un solo* intero e lo inizializza
al valore 600. Diversa e' l'espressione "new int[600]" (con le
parentesi quadre!).
Andrea

STL).
Condivido il consiglio di usare STL, ma solo dopo essersi
chiarita la confusione di base sulle allocazioni dinamiche.
HTH
Andrea

 alla grande del perche' e programma!
e invece si che me ne frega!!!
perche se devo caricare i dati in un oggetto tramite la lettura su un 
file,  è normale volere che i dati vengano caricati correttamente.
Insomma!!
un oggetto indica solo lo stato di una classe.
Quello che differisce tra una istanza e l'altra di una classe sono solo 
gli elementi che variano stato. Il suo stato è dato dalle sue variabili 
(naturalmente escluse quelle static).
Quindi in una istanza di chunck
struct chunck{
    	short id1;
 	short id2;
    	short id3;
    	short id4;
    	int len;
}obj;
io mi aspetto che l'oggetto abbia come dimensione la somma delle sue 
variabili.
Non può esistere un compilatore che si comporta in modo diverso neanche 
in fase di debug. Che cavolo se ne fa dei byte in più in una istanza?

 non trascurabili penalita' di prestazioni.
questa era la risposta che mi aspettavo.
Lo sospettavo. Sai dove posso reperire informazioni?
grazie.



Ci credo che si sovrapponevano! ;-)


 Cos'e' questo "destroy" ?
Sorry, delete() (salto da un linguaggio all'altro...)


 Lo sospettavo. Sai dove posso reperire informazioni?
documentazione del compilatore!


 in fase di debug. Che cavolo se ne fa dei byte in più in una istanza?
perche' avra' bisogno di fare padding per ottimizzare i trasferimenti di
memoria! per esempio, architetture come l'Alpha sono molto piu' veloci a fare
I/O di 64 bit che non di 32! quindi e' assolutamente normale che un
compilatore ottimizzi, che faccia padding delle strutture, e che tu non sappia
mai realmente quanto sono grandi, e che in debug si comporti diversamente che
in build release!
Inoltre, ribadisco che fai confusione tra le struct in C ed in C++!!!


ok, ho risolto.
grazie

> Inoltre, ribadisco che fai confusione tra le struct in C ed in C++!!!
Io vengo dal pascal. Il c non lo conosco.
Vuoi dire che dovrei usare class?
Lo dici tu che usi malloc per allocare una matrice dinamica in C++?

 seguito...
Intanto un'assegnazione ad un int matrX[600] (che e' un lvalue non
modificabile) dovrebbe dare errore in compilazione.  Poi new int(600)
alloca un solo intero, richiamandone il costruttore ed
inizializzandolo a 600; presumibilmente tu volevi new int[600].  Un
poco di ripasso alle basi del linguaggio ti farebbe bene.
-- 
Maurizio Loreti                         
http://www.pd.infn.it/~loreti/mlo.html
Dept. of Physics, Univ. of Padova, Italy          loreti at pd dot infn dot it

 e ora che ce l'hai?!?
risolvo il problema. 

 (Linux + gcc).
Io avrei usato  il g++. In C++ una struct e`  assimilabile ad una classe
(a  parte la  diversa  visibilita` di  default  dei membri). Quindi,  in
C++, e`  lecito scrivere  sizeof(chunck). In C, invece,  dovrai scrivere
sizeof(struct chunck).
ciao
Kronos
-- 
Home: 
http://kronoz.cjb.net