Newsgroup: it.comp.lang.c++
Titolo: Allocazione vettore di puntatori Borland Turbo C++ 3.1 su Ms-dos [Difficile]

Buongiorno a tutti quanti voi.
Devo dire, C++ mi stupisce sempre di più. In particolare il *vecchio*
Turbo C++ della Borland, vecchio del 1992. Ho un problema che è
il più strano del mondo. Vededete, ho creato uno struct che contiene
puntatori vari ad altri elementi struct, in più due valori unsigned int.
Fin qui niente di strano no? Allora, io devo creare dinamicamente un
vettore di N elementi. Cioè mettere tutto quello nell'heap. Con l'operatore
new estraiamo una qualantità di memoria necessaria per allocare il
vettore e mi restituisce il puntatore al primo elemento. Se questo è uguale
a 0 (null) vuol dire che non c'è memoria per metterlo in memoria (gioco di
parole che rende l'idea.. o le confonde?). Comunque non è neanche questo il
problema.
Facciamo un altro passo avanti. Se date una occhiata al codice qui sotto
noterete le struct. La struct prefix contiene 4 puntatori e due variabili
unsigned int.
i puntatori occupano 2 byte, le unsigned int altri 2 byte. Quindi sarebbero
4*2+2*2=12 byte.
Moltiplicato per la dimensione del vettore avremo 12*DIMENSIONE.
In più ho letto che quando allochiamo nello heap si occupa più memoria in
termini di byte,
che quando le allochiamo comunemente nello stack, perchè bisogna creare uno
spazio
che determini la  dimensione dell'"oggetto" (credo più più corretto
variabile)
puntato dal puntatore. Non ho idea di quanto sia realmente lo spazio
necessario.
Comunque adesso viene il *bello*: allochiamo con l'istruzione:
             prefix *vettorehashone=new prefix[(int)BERNI];
con BERNI=4000 il vettore. Funziona. Niente di strano. Adesso aumentiamo il
valore di BERNI. E arriviamo a 4886, e funziona ancora. Poniamo BERNI uguale
a 4887 e non funziona più. Restituisce il puntatore nullo. Aumentiamo ancora
BERNI
fino a 5462 e il puntatore viene ri-allocato senza nessun errore. Come è
possibile???
Fino a 4886 si poi no? prima di 5462 no e dopo si? Ma che? Mi prende in
giro?
Non è possibile direte voi. Invece è così. Premetto una cosa: questo succede
*solo*
con Turbo C++ che è basato sul vecchio Dos (sarà vecchio ma funziona..),
mentre
con Visual C++ tutto funziona regolarmente. Ma comunque è una cosa da pazzi!
Sono uno studente di 4 informatica, ho chiesto ai prof di tutte le classi,
nessuno ci capisce
niente..
Una cosa da dire c'è, anche se non so se sia giusta. Io eseguo Turbo C++ in
una finestra
di Ms-dos da windoz, che mette a disposizione del prompt solo 16mb. Ma
comunque,
se sono mettiamo 20 byte per elemento (esagerando sullo spazio riservato
alla dimensione)
20byte*5000=100.000byte, ossia 100kb (circa lo so..).
E non mi sembra che non ci siano a disposizione 100k in memoria per allocare
un vettore no?
Se vi ricordate il comando MEM da Dos scrive a video la dimensione massima
di un programma
eseguibile, che arriva ad oltre 500.000 byte. Quindi la memoria c'è. E ci
deve essere per forza
se riesco ad allocare un vettore di 6000. Ma perchè 5000 no??? Perchè???
Ringrazio tutti quelli che leggeranno questo luuuuuuungo messaggio ;-)
e ancora di più quelli che mi risponderanno!
bye Augusto
#include<iostream.h>
#include<fstream.h>
#include<dos.h>
#include<conio.h>
#include<string.h>
unsigned long const BERNI=5000;   //4886~5462
unsigned long const BERNI_PAROLE=1000;
int memoria=1;
int PippoZippo=0;
struct parole{
 char *word;
 parole *successivo;
 unsigned long *sign;
};
struct suffix{
 suffix *successivo;
 unsigned char associated;
 parole suffixone;
};
struct prefix{
 prefix *successivo;
 parole *first;
 parole *second;
 unsigned int associatedone;
 unsigned int associatedtwo;
 suffix *firstofall;
};
void main(void)
{
 //clrscr();
 ifstream infile;
 //ofstream
created("c:\\bcpp\\markov\\created.txt",ios::out|ios::noreplace);
 infile.open("c:\\bcpp\\markov\\created.txt");
 //infile.open("c:\\bcpp\\markov\\divina.txt");
 //infile.open("c:\\bcpp\\markov\\augusto.txt");
 //infile.open("c:\\bcpp\\markov\\commedia.txt");
 prefix *vettorehashone=new prefix[(int)BERNI];
 parole *vettoreparole=new parole[(int)BERNI_PAROLE];
//criticabile l'utilizzo di una costante per allocazione dinamica,
//ma nelle succesive "release" del programma lì ci sarà una variabile
 parole *temp=new parole;
 prefix *tmp=new prefix;
 if ((vettorehashone==0)||(vettoreparole==0)||(temp==0)||(tmp==0))
  {
   cout << "Memoria insufficente.";
   delete[] vettoreparole;
   delete[] vettorehashone;
   delete[] temp;
   delete[] tmp;
   unsigned long
necessaria=((sizeof(prefix)*BERNI)+(sizeof(parole)*BERNI_PAROLE)+(sizeof(par
ole))+(sizeof(prefix)));
   cout << "\nNecessari " <<necessaria;
   getch();
   return;
  }
 else
  {
   cout << "Allocated " << sizeof(prefix)*BERNI << " byte in
VettoreHashOne\n";
   cout << "Allocated " << sizeof(parole)*BERNI_PAROLE << " byte in
VettoreParole\n";
   cout << "Allocated " << sizeof(prefix) << " byte in Temp\n";
   cout << "Allocated " << sizeof(parole) << " byte in Tmp\n";
   unsigned long
necessaria=((sizeof(prefix)*BERNI)+(sizeof(parole)*BERNI_PAROLE)+(sizeof(par
ole))+(sizeof(prefix)));
   cout << "Total " <<necessaria;
   cout << "\nReady! Press any key!\n";
   //getch();
   //clrscr();
  }
  // qui ho tagliato il resto del programma
   delete[] vettoreparole;
   delete[] vettorehashone;
   delete[] temp;
   delete[] tmp;
 while(!kbhit());
}
struct parole{
 char *word;
 parole *successivo;
 unsigned long *sign;
};
struct suffix{
 suffix *successivo;
 unsigned char associated;
 parole suffixone;
};
struct prefix{
 prefix *successivo;
 parole *first;
 parole *second;
 unsigned int associatedone;
 unsigned int associatedtwo;
 suffix *firstofall;
};
void main(void)
{
 //clrscr();
 ifstream infile;
 //ofstream
created("c:\\bcpp\\markov\\created.txt",ios::out|ios::noreplace);
 infile.open("c:\\bcpp\\markov\\created.txt");
 //infile.open("c:\\bcpp\\markov\\divina.txt");
 //infile.open("c:\\bcpp\\markov\\augusto.txt");
 //infile.open("c:\\bcpp\\markov\\commedia.txt");
 prefix *vettorehashone=new prefix[(int)BERNI];
 parole *vettoreparole=new parole[(int)BERNI_PAROLE];
 parole *temp=new parole;
 prefix *tmp=new prefix;
 if ((vettorehashone==0)||(vettoreparole==0)||(temp==0)||(tmp==0))
  {
   cout << "Memoria insufficente.";
   delete[] vettoreparole;
   delete[] vettorehashone;
   delete[] temp;
   delete[] tmp;
   unsigned long
necessaria=((sizeof(prefix)*BERNI)+(sizeof(parole)*BERNI_PAROLE)+(sizeof(par
ole))+(sizeof(prefix)));
   cout << "\nNecessari " <<necessaria;
   getch();
   return;
  }
 else
  {
   cout << "Allocated " << sizeof(prefix)*BERNI << " byte in
VettoreHashOne\n";
   cout << "Allocated " << sizeof(parole)*BERNI_PAROLE << " byte in
VettoreParole\n";
   cout << "Allocated " << sizeof(prefix) << " byte in Temp\n";
   cout << "Allocated " << sizeof(parole) << " byte in Tmp\n";
   unsigned long
necessaria=((sizeof(prefix)*BERNI)+(sizeof(parole)*BERNI_PAROLE)+(sizeof(par
ole))+(sizeof(prefix)));
   cout << "Total " <<necessaria;
   cout << "\nReady! Press any key!\n";
   //getch();
   //clrscr();
  }
  // qui ho tagliato il resto del programma
   delete[] vettoreparole;
   delete[] vettorehashone;
   delete[] temp;
   delete[] tmp;
 while(!kbhit());
}

puntatori vari ad altri elementi struct, in più due valori unsigned int.
[cut]
... in questo momento non ho voglia di leggermi e/o provare il tuo
codice... anche perche' non ho ancora preso il caffe' :-P
comunque, se non ricordo male, considera che:
1. La dimensione di una struttura dipende anche dall'allineamento
scelto (word, byte, dword) quindi il tuo calcolo dei 12 byte potrebbe
non essere giustissimo
2. Per ogni singola allocazione non puoi comunque allocare + di 64K
3. La somma di tutte le allocazioni deve essere compatibile con la
quantità di memoria presente sulla macchina (o nel tuo caso messa a
disposizione dal winsozz) e a quella prevista nel modello di memoria
scelto...
ciao
Andrea

> 2. Per ogni singola allocazione non puoi comunque allocare + di 64K
mi pare che questo sia proprio quello che non va.. grazie, augustus

> 2. Per ogni singola allocazione non puoi comunque allocare + di 64K
Questo in Dos? Sai il perchč?



... il perche' bisognerebbe chiederlo al solito "Giovanni Cancelli"
:-) ... comunque il tutto e' dovuto alla segmentazione della memoria e
alla dimensione dei puntatori o quanto meno alla volonta' di mantenere
la massima compatibilita' con il passato...
Tutto cio' vale ovviamente per Dos ma, sempre in nome della piena
compatibilita', te lo ritrovi anche, ad esempio, in Win32. Ovviamente
poi a fianco di new troverai delle API che ti permettono di allocare
ben piu' di 64K !
Comunque se a te interessa solo il Dos non disperare! ...e dai
un'occhiata all'help della farmalloc che consente appunto allocazioni
di 64K. 
ciao
Andrea

 ... il perche' bisognerebbe chiederlo al solito "Giovanni Cancelli"
                                                   ^^^^^^^^
                                                   Guglielmo ;-)
Ciao,
Nicola

> ... il perche' bisognerebbe chiederlo al solito "Giovanni Cancelli"
poi si è scoperto che si chiama Guglielmo..
e allora:
Guglielmo!!!
Tu sai qualcosa???
Thanks, good byte, Augustus