PDA

Visualizza la versione completa : [C++] Doppio puntatore e calcolo del determinante di una matrice quadrata


FinalFantasy
06-03-2007, 00:03
Ciaoa a tutti,
ho fatto una piccola applicazione che calcola il Determinante di una matrice quadrata. Ecco il codice del main (e li dove si verifica il tutto):


int main()
{
int **matrix;
int n;
ifstream leggi;
leggi.open("input.txt");
//leggo l'ordine della matrice
leggi>>n;
//istanzio la matrice
matrix = new (int *);
for(int i =0;i<n;i++)
{
matrix[i]=new int;
}
//leggo la matrice da file
for (int riga=0;riga<n;riga++)
{
for (int colonna=0;colonna<n;colonna++)
{
leggi>>matrix[riga][colonna];
}
}

for (int riga=0;riga<n;riga++)
{
for (int colonna=0;colonna<n;colonna++)
{

cout<<matrix[riga][colonna]<<" ";
}
cout<<"\n";
}

cout<<"Il determinante della matrice : "<<Determinante(matrix,n);


delete matrix;
}

il problema sta nel fatto che, se io gli dico di leggere una matrice 3x3 (il leggi>>n prende il primo numero dal file che indica l'ordine della matrice, 3x3, 4x4 etc.)

Se prende 3, ok, se prende 2, ok, se prende 4 guardate le belle cose che mi dice



$ g++ -pedantic -Os determinante.cpp -o determinante
determinante.cpp:90:2: warning: no newline at end of file
>Exit code: 0
$./determinante
*** glibc detected *** ./determinante: free(): invalid next size (fast): 0x0804c178 ***
======= Backtrace: =========
/lib/tls/i686/cmov/libc.so.6[0xb7d4c8bd]
/lib/tls/i686/cmov/libc.so.6(__libc_free+0x84)[0xb7d4ca44]
/usr/lib/libstdc++.so.6(_ZdlPv+0x21)[0xb7efbfc1]
./determinante(__gxx_personality_v0+0x34e)[0x8048af2]
/lib/tls/i686/cmov/libc.so.6(__libc_start_main+0xdc)[0xb7cfb8cc]
./determinante(__gxx_personality_v0+0x6d)[0x8048811]
======= Memory map: ========
08048000-08049000 r-xp 00000000 16:06 153028 /home/tuttoweb/documenti/programmazione/c++/determinante/determinante
08049000-0804a000 rw-p 00000000 16:06 153028 /home/tuttoweb/documenti/programmazione/c++/determinante/determinante
0804a000-0806b000 rw-p 0804a000 00:00 0 [heap]
b7b00000-b7b21000 rw-p b7b00000 00:00 0
b7b21000-b7c00000 ---p b7b21000 00:00 0
b7ce5000-b7ce6000 rw-p b7ce5000 00:00 0
b7ce6000-b7e13000 r-xp 00000000 16:06 294929 /lib/tls/i686/cmov/libc-2.4.so
b7e13000-b7e15000 r--p 0012c000 16:06 294929 /lib/tls/i686/cmov/libc-2.4.so
b7e15000-b7e17000 rw-p 0012e000 16:06 294929 /lib/tls/i686/cmov/libc-2.4.so
b7e17000-b7e1a000 rw-p b7e17000 00:00 0
b7e1a000-b7e24000 r-xp 00000000 16:06 262211 /lib/libgcc_s.so.1
b7e24000-b7e25000 rw-p 00009000 16:06 262211 /lib/libgcc_s.so.1
b7e25000-b7e49000 r-xp 00000000 16:06 294933 /lib/tls/i686/cmov/libm-2.4.so
b7e49000-b7e4b000 rw-p 00023000 16:06 294933 /lib/tls/i686/cmov/libm-2.4.so
b7e4b000-b7f1f000 r-xp 00000000 16:06 297220 /usr/lib/libstdc++.so.6.0.8
b7f1f000-b7f22000 r--p 000d4000 16:06 297220 /usr/lib/libstdc++.so.6.0.8
b7f22000-b7f24000 rw-p 000d7000 16:06 297220 /usr/lib/libstdc++.so.6.0.8
b7f24000-b7f2b000 rw-p b7f24000 00:00 0
b7f38000-b7f3a000 rw-p b7f38000 00:00 0
b7f3a000-b7f53000 r-xp 00000000 16:06 262168 /lib/ld-2.4.so
b7f53000-b7f55000 rw-p 00018000 16:06 262168 /lib/ld-2.4.so
bfb21000-bfb37000 rw-p bfb21000 00:00 0 [stack]
ffffe000-fffff000 ---p 00000000 00:00 0 [vdso]
0 7 2 2
-1 5 1 2
0 0 1 -1
0 4 0 2
Il determinante della matrice : 3Aborted (core dumped)
>Exit code: 134

voi ci capite qualcosa?

oregon
06-03-2007, 08:22
La matrice non e' allocata/liberata correttamente e quando va a leggere i dati, accede a zone di memoria non lecite.

Quando allochi deve essere



matrix = new int*[n];
for(i=0;i<n;i++)
matrix[i] = new int[n];


e quando liberi



for(i=0;i<n;i++)
delete matrix[i];
delete matrix;

mondobimbi
06-03-2007, 08:59
Originariamente inviato da oregon


...
e quando liberi



for(i=0;i<n;i++)
delete matrix[i];
delete matrix;

o forse?

.....
delete [] matrix;
ciao
sergio

oregon
06-03-2007, 10:07
Originariamente inviato da mondobimbi
o forse?

.....
delete [] matrix;
ciao
sergio

Formalmente s, ma il compilatore (nel mio caso VC2005) e' abbastanza "smart" da capire cosa sta facendo ... infatti, a livello di codice compilato, per le due forme



delete matrix;
00411CFD 8B 45 F8 mov eax,dword ptr [matrix]
00411D00 89 85 14 FF FF FF mov dword ptr [ebp-0ECh],eax
00411D06 8B 8D 14 FF FF FF mov ecx,dword ptr [ebp-0ECh]
00411D0C 51 push ecx
00411D0D E8 D8 F4 FF FF call operator delete (4111EAh)
00411D12 83 C4 04 add esp,4

delete [] matrix;
00411CFD 8B 45 F8 mov eax,dword ptr [matrix]
00411D00 89 85 14 FF FF FF mov dword ptr [ebp-0ECh],eax
00411D06 8B 8D 14 FF FF FF mov ecx,dword ptr [ebp-0ECh]
00411D0C 51 push ecx
00411D0D E8 0B F9 FF FF call operator delete[] (41161Dh)
00411D12 83 C4 04 add esp,4


come puoi vedere, non c'e' differenza.

Ciao

mondobimbi
06-03-2007, 10:45
Originariamente inviato da oregon
Formalmente s, ma il compilatore (nel mio caso VC2005) e' abbastanza "smart" da capire cosa sta facendo ... infatti, a livello di codice compilato, per le due forme



delete matrix;
00411CFD 8B 45 F8 mov eax,dword ptr [matrix]
00411D00 89 85 14 FF FF FF mov dword ptr [ebp-0ECh],eax
00411D06 8B 8D 14 FF FF FF mov ecx,dword ptr [ebp-0ECh]
00411D0C 51 push ecx
00411D0D E8 D8 F4 FF FF call operator delete (4111EAh)
00411D12 83 C4 04 add esp,4

delete [] matrix;
00411CFD 8B 45 F8 mov eax,dword ptr [matrix]
00411D00 89 85 14 FF FF FF mov dword ptr [ebp-0ECh],eax
00411D06 8B 8D 14 FF FF FF mov ecx,dword ptr [ebp-0ECh]
00411D0C 51 push ecx
00411D0D E8 0B F9 FF FF call operator delete[] (41161Dh)
00411D12 83 C4 04 add esp,4


come puoi vedere, non c'e' differenza.

Ciao
come non c' differenza, le due chiamate sono ad indirizzi differenti.
La chiamata a
delete matrix;
disalloca solo il primo elemento.
ciao
sergio

oregon
06-03-2007, 11:02
L'indirizzo e' differente perche' viene chiamato l'operatore delete [] al posto del delete.
In effetti mi ero dimenticato di mostrarti che l'operatore delete [] e' definito con



void operator delete[]( void * p )
{
RTCCALLBACK(_RTC_Free_hook, (p, 0))

operator delete(p);
}


e come puoi vedere (a meno della prima indicazione che e' usata solamente per il debug), il tutto si risolve alla corrispondente chiamata all'operatore delete a cui viene passato il puntatore originale. Avviene tutto all'interno del codice dell'operatore delete.

E poi perche' parli di "primo elemento"? La deallocazione avviene del "blocco di memoria" costituito dallo spazio necessario ad allocare n puntatori, spazio che e' contiguo in memoria.

mondobimbi
06-03-2007, 12:32
l'uso dell'operatore delete invece di delete [] su degli array allocati dinamicamente d risultati non definiti dalle specifiche del c++, l'implementazione lasciata libera al compilatore, molte volte questi disallocano solo il primo elemento.
Non conosco il comportamento di VC2005 ma se si vuole scrivere codice portabile meglio disallocare sempre gli array con delete [] .
ciao
sergio

FinalFantasy
07-03-2007, 00:09
alla fine come si deleta?

oregon
07-03-2007, 00:24
Beh ... il discorso mi e' sembrato abbastanza chiaro ...

FinalFantasy
11-03-2007, 01:51
Originariamente inviato da oregon
La matrice non e' allocata/liberata correttamente e quando va a leggere i dati, accede a zone di memoria non lecite.

Quando allochi deve essere



matrix = new int*[n];
for(i=0;i<n;i++)
matrix[i] = new int[n];


e quando liberi


non voglio aprire un altro thread, ma ho questo problema


modulo **castello;

input.open("input.txt");
input>>r;input>>c;

castello = new modulo *[r];
for(int i =0;i<r;i++)
{
castello[i]=new modulo [c];
}

dove modulo una struct cos definita

struct modulo
{
char visitato;
modulo *to_west;
modulo *to_north;
modulo *to_east;
modulo *to_south;
};


mi dice:
terminate called after throwing an instance of 'std::bad_alloc'
what(): St9bad_alloc
Aborted (core dumped)


suggerimenti?

Loading