Newsgroup: it.comp.lang.c++
Titolo: caccia al bug

Salve ragazzi,
ho scritto per allenamento questo programma.
Funziona quasi tutto a dovere solo che se inserisco i seguenti valori
 
righe 3
numero massimo di colonne 4
colonne 1° array 4
colonne 2° array 3
colonne 3° array 2
 
il programma va in crash e non riesco a immaginarne il motivo.
Conto sul vostro aiuto ;o)
 
grazie,
alessandro
 
*cut here*
 
#include <iostream>
#include <climits>  // utilizzato per LONG_MAX
#include <cstdlib>  // utilizzato per srand e rand
#include <ctime>    // utilizzato per time()
 
using std::cout;
using std::cin;
using std::endl;
 
void stampa_array(int **, int, int *);
void azzera_array(int **, int, int *);
void riempi_array(int **, int, int *);
void rilascia_memoria(int **, int);
 
 
int main()
{
     int col_max = 0;    // memorizza il numero massimo di colonne 
dell'array
     int righe = 0;      // memorizza il numero di righe dell'array
 
     char input = '\0';
     bool esci = false;
 
     int ** array = 0;   // l'array sullo heap
     int *colonne = 0;   // il numero di colonne per ciascuna riga
 
     // imposta il seme del random
     // utilizzando l'ora corrente
 
     srand(time(0));
 
     do
     {
         cout << "Inerisci quante righe ha l'array: ";
 
         // la procedura che segue permette di gestire
         // un input errato
 
         while((cin >> righe) == 0 )
         {
             cin.clear();
             cin.ignore(LONG_MAX,'\n');
 
             // a rigore dovrei usare
             // cin.ignore(numeric_limits<streamsize>::max() ,'\n')
             // ma il mio compilatore non
             // lo supporta ancora
 
             cout << "Per favore reinserisci: ";
         }
 
         cout << "Inerisci quante colonne ha la riga più lunga: ";
 
         while((cin >> col_max) == 0 )
         {
             cin.clear();
             cin.ignore(LONG_MAX,'\n');
 
             // a rigore dovrei usare
             // cin.ignore(numeric_limits<streamsize>::max() ,'\n')
             // ma il mio compilatore non
             // lo supporta ancora
 
             cout << "Per favore reinserisci: ";
         }
 
         try
         {
             array = new int * [righe];
 
             colonne = new int [righe];
 
             for(int i=0; i < col_max; i++)
             {
                 colonne[i] = 0;
             }
         }
         catch(...)
         {
             cout << "Errore di allocazione,"
                     " memoria non sufficiente." << endl;
         }
 
 
         int loop_counter = righe;
         int column_index = 0;
 
         while(loop_counter > 0)
         {
             cout << "inserisci il numero di colonne del "
                  << column_index + 1 <<  " ° array ";
 
             while((cin >> colonne[column_index]) == 0 )
             {
                 cin.clear();
                 cin.ignore(LONG_MAX,'\n');
 
                 // a rigore dovrei usare
                 // cin.ignore(numeric_limits<streamsize>::max() ,'\n')
                 // ma il mio compilatore non
                 // lo supporta ancora
 
                 cout << "Per favore reinserisci: ";
             }
 
             if(colonne[column_index] > col_max)
             {
                 cout << "l'array puo\' avere al massimo "
                      << col_max << " colonne." << endl;
                 continue;
             }
 
             column_index ++;
             loop_counter--;
         }
 
         try
         {
             for(int i=0; i < righe; i++)
             {
                 array[i] = new int [colonne[i]];
             }
         }
         catch(...)
         {
             cout << "Errore, di allocazione"
                     " memoria non disponibile." << endl;
         }
 
         azzera_array(array, righe, colonne);
         riempi_array(array, righe, colonne);
         stampa_array(array, righe, colonne);
 
         rilascia_memoria(array, righe);
 
         delete[] colonne;
         colonne = 0;
 
 
         cout << "\nTerminare il programma? Si/No: ";
 
         cin >> input;
 
         while( !(tolower(input == 's') || (tolower(input) == 'n')) )
         {
 
             cin.clear();
             cin.ignore(LONG_MAX,'\n');
 
             // a rigore dovrei usare
             // cin.ignore(numeric_limits<streamsize>::max() ,'\n')
             // ma il mio compilatore non
             // lo supporta ancora
 
             cout << "Per favore reinserisci: ";
             cin >> input;
         }
 
         if(tolower(input) == 's')
         {
             esci = true;
             break;
         }
         else
         {
             esci = false;
             continue;
         }
 
 
         return 0;
 
     }while(esci == false);
 
 
}
 
void azzera_array(int ** array_p, int N_sz, int * col)
{
     for(int i=0 ; i < N_sz; i++)
     {
         for(int j = 0; j < col[i]; j++)
         {
             array_p[i][j] = 0;
         }
     }
}
 
void riempi_array(int ** array_p, int N_sz, int * col)
{
     for(int i=0 ; i < N_sz; i++)
     {
         for(int j = 0; j < col[i]; j++)
         {
             array_p[i][j] = rand() % 10;
         }
     }
}
 
void stampa_array(int ** array_p, int N_sz, int * col)
{
     cout << endl;
 
     for(int i=0; i < N_sz; i++)
     {
         for(int j=0; j < col[i]; j++)
         {
             cout << array_p[i][j] << " ";
         }
         cout << endl;
     }
}
 
     // rand % 10 imposta il numero
     // casuale in modo che sia
     // compreso tra 0 e 9
 
void rilascia_memoria(int ** array_p, int N_sz)
{
     for(int i=0; i < N_sz; i++)
     {
         delete[] array_p[i];
         array_p[i] = 0;
     }
 
     delete array_p;
     array_p = 0;
 
     cout << "\nmemoria rilasciata." << endl;
}

      delete array_p;
 
Deve essere: delete[] array_p;
 
Sei fortunato che ti vada in crash il programma, perchï¿œ quell'errore
genera comportamento indefinito, cioï¿œ non c'e' garanzia che il programma
venga interrotto e quindi l'errore potrebbe passare inosservato in fase
d'esecuzione (come nel mio caso).
 
Se avessi usato un vettore di vettori standard come struttura dati,
anzichï¿œ un array di array, oltre a rendere il codice piï¿œ corto e
leggibile, non saresti incorso nell'errore, perchï¿œ non avresti dovuto
occuparti esplicitamente della gestione della memoria,
 

 occuparti esplicitamente della gestione della memoria,
 
lo proverò come esercizio.
 
grazie
 

 occuparti esplicitamente della gestione della memoria,
 
il fatto è che ho imparato a programmare e per diversi anni ho
programmato solo con il C e sto facendo la transizione a C++.
Certo il mio livello non è elevato, ma non mi devo guadagnare il
pane con questo mio hobby.
 

Se eseguo il ciclo una sola volta,
questo è il log del messaggio di errore:
 
jagged_array_bis: malloc.c:3097: sYSMALLOc: Assertion `(old_top == 
(((mbinptr) (((char *) &((av)->bins[((1) - 1) * 2])) - 
__builtin_offsetof (struct malloc_chunk, fd)))) && old_size == 0) || 
((unsigned long) (old_size) >= (unsigned long)((((__builtin_offsetof 
(struct malloc_chunk, fd_nextsize))+((2 * (sizeof(size_t))) - 1)) & 
~((2 * (sizeof(size_t))) - 1))) && ((old_top)->size & 0x1) && 
((unsigned long)old_end & pagemask) == 0)' failed.
 
se eseguo il ciclo almeno due volte,
questo è il messaggio di errore
 
*** glibc detected *** /home/alessandro/Documenti/ProgC/jagged 
array/bin/Debug/jagged_array_bis: free(): invalid pointer: 0x09e96018 ***
======= Backtrace: =========
/lib/i686/cmov/libc.so.6(+0x6af71)[0xb754ff71]
/lib/i686/cmov/libc.so.6(+0x6c7c8)[0xb75517c8]
/lib/i686/cmov/libc.so.6(cfree+0x6d)[0xb75548ad]
/usr/lib/libstdc++.so.6(_ZdlPv+0x21)[0xb772c701]
/usr/lib/libstdc++.so.6(_ZdaPv+0x1d)[0xb772c75d]
/home/alessandro/Documenti/ProgC/jagged 
array/bin/Debug/jagged_array_bis[0x804924c]
/home/alessandro/Documenti/ProgC/jagged 
array/bin/Debug/jagged_array_bis[0x8048f48]
/lib/i686/cmov/libc.so.6(__libc_start_main+0xe6)[0xb74fbca6]
/home/alessandro/Documenti/ProgC/jagged 
array/bin/Debug/jagged_array_bis[0x8048a81]
======= Memory map: ========
08048000-0804a000 r-xp 00000000 08:01 336460 
/home/alessandro/Documenti/ProgC/jagged array/bin/Debug/jagged_array_bis
0804a000-0804b000 rw-p 00001000 08:01 336460 
/home/alessandro/Documenti/ProgC/jagged array/bin/Debug/jagged_array_bis
09e96000-09eb7000 rw-p 00000000 00:00 0          [heap]
b7300000-b7321000 rw-p 00000000 00:00 0
b7321000-b7400000 ---p 00000000 00:00 0
b74e4000-b74e5000 rw-p 00000000 00:00 0
b74e5000-b7625000 r-xp 00000000 08:01 352695 
/lib/i686/cmov/
libc-2.11.3.so
 
b7625000-b7626000 ---p 00140000 08:01 352695 
/lib/i686/cmov/
libc-2.11.3.so
 
b7626000-b7628000 r--p 00140000 08:01 352695 
/lib/i686/cmov/
libc-2.11.3.so
 
b7628000-b7629000 rw-p 00142000 08:01 352695 
/lib/i686/cmov/
libc-2.11.3.so
 
b7629000-b762c000 rw-p 00000000 00:00 0
b762c000-b7649000 r-xp 00000000 08:01 335875     /lib/libgcc_s.so.1
b7649000-b764a000 rw-p 0001c000 08:01 335875     /lib/libgcc_s.so.1
b764a000-b764b000 rw-p 00000000 00:00 0
b764b000-b766f000 r-xp 00000000 08:01 352677 
/lib/i686/cmov/
libm-2.11.3.so
 
b766f000-b7670000 r--p 00023000 08:01 352677 
/lib/i686/cmov/
libm-2.11.3.so
 
b7670000-b7671000 rw-p 00024000 08:01 352677 
/lib/i686/cmov/
libm-2.11.3.so
 
b7671000-b775a000 r-xp 00000000 08:01 1517391 
/usr/lib/libstdc++.so.6.0.13
b775a000-b775e000 r--p 000e9000 08:01 1517391 
/usr/lib/libstdc++.so.6.0.13
b775e000-b775f000 rw-p 000ed000 08:01 1517391 
/usr/lib/libstdc++.so.6.0.13
b775f000-b7766000 rw-p 00000000 00:00 0
b7777000-b777b000 rw-p 00000000 00:00 0
b777b000-b777c000 r-xp 00000000 00:00 0          [vdso]
b777c000-b7797000 r-xp 00000000 08:01 335888     /lib/
ld-2.11.3.so
 
b7797000-b7798000 r--p 0001b000 08:01 335888     /lib/
ld-2.11.3.so
 
b7798000-b7799000 rw-p 0001c000 08:01 335888     /lib/
ld-2.11.3.so
 
bfe0e000-bfe23000 rw-p 00000000 00:00 0          [stack]
Aborted
 


 
Dopo:
            colonne = new int [righe];
 
hai:
             for(int i=0; i < col_max; i++)
             {
                 colonne[i] = 0;
 
 
forse volevi:
             for(int i=0; i < righe; i++)
             {
                 colonne[i] = 0;
 


Bravo, ci sei riuscito!
Non si blocca più. Grazie
Te l'ho detto che sono ancora apprendista no? ;o)


ho commesso l'errore di accedere all'array oltr i suoi naturali 
limiti, errore da dilettante proprio, però quando dicono che questi 
sono errori difficili da scovare hanno ragione!, io non lo avevo visto.
 
Ancora grazie, Luca