Nie jesteś zalogowany.
Jeśli nie posiadasz konta, zarejestruj je już teraz! Pozwoli Ci ono w pełni korzystać z naszego serwisu. Spamerom dziękujemy!
Prosimy o pomoc dla małej Julki — przekaż 1% podatku na Fundacji Dzieciom zdazyć z Pomocą.
Więcej informacji na dug.net.pl/pomagamy/.
Strony: 1
Męczę się już trzeci tydzień z tym... żeby nie napisać bardzo brzydkiego słowa, cholernym programem.
Dla macierzy 2x2 liczy ladnie, dam mu 3x3 już krzyczy że naruszenie ochrony pamięci. Podejrzewam, że błąd leży w tych dwóch zagnieżdżonych for'ach ale ze mnie dupa, nie programista wiec mam kilka procent niepewności.
Tak się już do niego zraziłam, że nie kontaktuję co czytam jak patrzę w "kod". Tyle nerwów mi naszarpał że nawet patrzeć już nie chcę. Chcę tylko zrobić taki myk żeby działał i już nigdy więcej go nie otwierać.
Dla ciekawskich, struktura pliku wygląda tak:
2 <-rozmiar macierzy, poniżej macierz
3 4
5 6
#include <iostream> #include <stdlib.h> #include <stdio.h> #include <math.h> using namespace std; double** create_matrix (int stopien) { double** macierz; if (stopien < 1) { cout<<"bledny rozmiar!"<<endl; exit (-1); } *macierz = (double*) calloc(stopien*stopien, sizeof(double)); return macierz; } double det(double ** matrix, int n) { double** minor; double sum=0.0; double sign=1.0; int i, nr_row, nr_col, nr_col_dop; //nr wiersza,nr kolumny, nr kolumny dopelnienia if(n==1) return matrix[0][0]; if(n==2) return matrix[0][0]*matrix[1][1]-matrix[0][1]*matrix[1][0]; minor=create_matrix(n-1); for(i=0;i<n;i++) { /* skopiuj odp. podmacierz do minor */ for (nr_col_dop = 0, nr_col = 0; nr_col_dop < n-1; nr_col_dop++, nr_col++) { nr_col += (nr_col == nr_col ? 1 : 0); for (nr_row = 0; nr_row < n-1; nr_row++) minor[nr_row][nr_col_dop] = matrix[nr_row+1][nr_col]; } sum+=sign*matrix[0][i]*det(minor,n-1); sign = -sign; }; free(minor); return sum; }; int main(int argc, char** argv) { int rozmiar, x, i=0, j=0; FILE *plik; plik=fopen("macierz.txt", "r"); if(plik==NULL){ cout<<"Podany plik nie istnieje"<<endl; } fscanf(plik, "%d", &rozmiar); printf("\n"); printf("Rozmiar macierzy wynosi: %d x %d\n\n", rozmiar, rozmiar); double** matrix=new double*[rozmiar]; for(x = 0; x<=rozmiar; x++){ matrix[x]=new double[rozmiar]; } printf("Nasza macierz: \n"); j=0; while(j<rozmiar){ i = 0; while(i<rozmiar){ fscanf(plik, "%lf", &matrix[i][j]); printf("%.2lf\t", matrix[i][j]); i++; } printf("\n"); ++j; } printf("\n"); printf("Wartosc wyznacznika macierzy wynosi: %lf\n", det(matrix, rozmiar)); fclose(plik); return 0; }
Jakiś mały hint dla blondyneczki?
Offline
Z tym jest chyba (chyba bo i dla rozmiaru 2 nie powinno działać) problem:
double** matrix=new double*[rozmiar]; for(x = 0; x<=rozmiar; x++){ matrix[x]=new double[rozmiar]; }
matrix ma rozmiar powiedzmy 2, więc masz tylko matrix[0] i matrzix[1], a w pętli spróbuje jeszcze ustawić matix[2]. Wszystko przez x<=rozmiar, powinno być "<" zamiast "<=".
Ostatnio edytowany przez kamikaze (2011-11-05 18:30:17)
Offline
Z tym tak - miałeś rację, ale nadal się wywala. Problem tkwi chyba w kopiowaniu elementów jednej macierzy do drugiej.
Offline
To też jest bez sensu:
nr_col += (nr_col == nr_col ? 1 : 0);
Warunek zawsze jest true, coś tu jest nie tak. Można równie dobrze zastąpić to krótko: nr_col++ . A to niesie ze sobą poważne konsekwencje:
Dla n = 3:
dla nr_col_dop = 0, nr_col = 0
nr_col = 1 (zwiększanie o 1)
minor[0][0] = matrix[1][1]
minor[1][0] = matrix[2][1]
nr_col_dop = 1, nr_col = 2 (zwiększanie w pętli, ale nr_col już jest 1, więc zwiększa się do 2)
nr_col = 3 (zwiększanie o 1)
minor[0][1] = matrix[1][3] < --- segfault (nie ma tej komórki, bo to macież 3x3, a nie 4x4)
minor[1][1] = matrix[2][3] < --- segfault ( — || — )
I błąd naruszenia ochrony pamięci znaleziony.
To chyba można zmienić:
for(i=0;i<n;i++) { /* skopiuj odp. podmacierz do minor */ for (nr_col_dop = 0, nr_col = 0; nr_col_dop < n-1; nr_col_dop++, nr_col++) { nr_col += (nr_col == nr_col ? 1 : 0); for (nr_row = 0; nr_row < n-1; nr_row++) minor[nr_row][nr_col_dop] = matrix[nr_row+1][nr_col]; } sum+=sign*matrix[0][i]*det(minor,n-1); sign = -sign; };
na:
/* skopiuj odp. podmacierz do minor */ for (nr_col_dop = 0, nr_col = 0; nr_col_dop < n-1; nr_col_dop++, nr_col++) { nr_col += (nr_col == nr_col ? 1 : 0); for (nr_row = 0; nr_row < n-1; nr_row++) minor[nr_row][nr_col_dop] = matrix[nr_row+1][nr_col]; } for(i=0;i<n;i++) { sum+=sign*matrix[0][i]*det(minor,n-1); sign = -sign; };
Bo tak jak jest obecnie to kopiuje się za każdym obrotem pętli, wygląda że nie potrzebnie. Najlepiej na kopiowanie zrobić oddzielną funkcję.
Offline
Do tego co podał Kamikaze należy dorzucić błąd w funkcji create_matrix, alokowałaś tam coś na kształt wektora zamiast macierzy 2D, pod spodem umieszczam kod który (chyba ;] ) alokuje poprawnie, aczkolwiek, jako że z calloc'a korzystałem pierwszy raz to mogę się mylić (nie wiem też czy możesz sobie macierz 2D z dealkokwać za pomocą po prostu "free(cośtam)", pewnie i tam trzeba by to zrobić z pętlą. Poniższy kod nie sypie się i wyznacznik drugiego poziomu zdaje się liczyć ok, ale trzeciego poziomu wyszedł mi niezbyt dobry - ale to już pewnie gdzieś błąd w samym algorytmie obliczającym.
#include <iostream> #include <stdlib.h> #include <stdio.h> #include <math.h> using namespace std; double** create_matrix (int stopien) { double** macierz; if (stopien < 1) { cout<<"bledny rozmiar!"<<endl; exit (-1); } macierz=(double**) calloc(stopien*stopien,sizeof(double)); for(int i=0;i<stopien;++i) { macierz[i] = (double*) calloc(stopien*stopien, sizeof(double)); } return macierz; } double det(double ** matrix, int n) { double** minor; double sum=0.0; double sign=1.0; int i, nr_row, nr_col, nr_col_dop; //nr wiersza,nr kolumny, nr kolumny dopelnienia if(n==1) return matrix[0][0]; if(n==2) return matrix[0][0]*matrix[1][1]-matrix[0][1]*matrix[1][0]; minor=create_matrix(n-1); for(i=0;i<n;i++) { /* skopiuj odp. podmacierz do minor */ for (nr_col_dop = 0, nr_col = 0; nr_col_dop < n-1; nr_col_dop++, nr_col++) { nr_col += (nr_col == nr_col ? 1 : 0); for (nr_row = 0; nr_row < n-1; nr_row++) minor[nr_row][nr_col_dop] = matrix[nr_row+1][nr_col]; } sum+=sign*matrix[0][i]*det(minor,n-1); sign = -sign; }; free(minor); return sum; }; int main(int argc, char** argv) { int rozmiar, x, i=0, j=0; FILE *plik; plik=fopen("macierz.txt", "r"); if(plik==NULL) { cout<<"Podany plik nie istnieje"<<endl; return -1; } fscanf(plik, "%d", &rozmiar); printf("\n"); printf("Rozmiar macierzy wynosi: %d x %d\n\n", rozmiar, rozmiar); double** matrix=new double*[rozmiar]; for(x = 0; x<rozmiar; ++x) { matrix[x]=new double[rozmiar]; } printf("Nasza macierz: \n"); j=0; while(j<rozmiar) { i = 0; while(i<rozmiar) { fscanf(plik, "%lf", &matrix[i][j]); printf("%.2lf\t", matrix[i][j]); ++i; } printf("\n"); ++j; } printf("\n"); printf("Wartosc wyznacznika macierzy wynosi: %lf\n", det(matrix, rozmiar)); fclose(plik); return 0; }
Tak poza tym to radziłbym się zdecydować na używanie albo funkcji C albo C++, mieszanie calloc/malloc/cosalloc z new i delete to praktyka bardzo "bee" i łatwo można się na tym przejechać (jak się np. da delete na coś co było alokowane za pomocą calloc'a - wiem z doświadczenia ;] ) podobnie w przypadku wypisywania, raz używanie cout, a raz print'a też niebyt fajnie wygląda.
Pozdro.
Offline
Hmmm macierze to aż proszą się o użycie klas... Trin macie jakieś ograniczenie co do tego co możecie użyć w tym programie?
Offline
thalcave napisał(-a):
Hmmm macierze to aż proszą się o użycie klas... Trin macie jakieś ograniczenie co do tego co możecie użyć w tym programie?
Niestety tak, facet zostawił nam "szkic" funkcji det i jazda. ->tzn oficjalnie mamy jeszcze nie wiedzieć co to klasy.
@up: obaj macie rację we wszystkim co mi napisaliście (dziękuję), ale były 3 wersje kodu okrawane z tego co zbędne, więc całość przypomina jakieś puzzle.
Ostatnio edytowany przez Trin (2011-11-05 23:38:41)
Offline
Trin to daj teraz cały kod jaki masz :) żebyśmy puzzli nie składali
Offline
Teraz ten kod wywala jakiś armagedon w konsoli. Ja mam dość :<
Offline
Tym bardziej wrzuć tutaj to obczaimy ;] C/C++ ma to do siebie że nawet osoby doświadczone potrafią się często złapać na alokacji/dealokacji pamięci (przez to głównie, te języki są uważane za trudne).
Ostatnio edytowany przez Huk (2011-11-06 07:28:39)
Offline
Dobra, poprawiłam parę rzeczy, m.in zwalnianie tablicy.
Trochę zapuściłam żurawia do kodu kolegi, ale to są jaja jakieś. Poprawiłam też pętle itp.
#include <iostream> #include <stdlib.h> #include <stdio.h> #include <math.h> using namespace std; double** create_matrix (int stopien) { double** macierz; if (stopien < 1) { cout<<"bledny rozmiar!"<<endl; exit (-1); } *macierz = (double*) calloc(stopien, sizeof(double)); for(int i=0;i<stopien;++i) { macierz[i] = (double*) calloc(stopien, sizeof(double)); } return macierz; } void matrix_free(double **macierz, int n){ for(int i=0;i<n;++i){ //Zwolnienie pamięci delete [] macierz[i]; } delete [] macierz; } double det(double ** matrix, int n) { double** minor; double sum=0.0; double sign=1.0; int i, nr_row, nr_col, nr_col_dop; //nr wiersza,nr kolumny, nr kolumny dopelnienia if(n==1) return matrix[0][0]; if(n==2) return matrix[0][0]*matrix[1][1]-matrix[0][1]*matrix[1][0]; minor=create_matrix(n-1); for(i=0;i<n;i++) { /* skopiuj odp. podmacierz do minor */ for (nr_col_dop = 0, nr_col = 0; nr_col_dop < n-1; nr_col_dop++, nr_col++) { nr_col += (nr_col == nr_col ? 1 : 0); //do poprawy, te dwa fory cuchną... for (nr_row = 0; nr_row < n-1; nr_row++) minor[nr_row][nr_col_dop] = matrix[nr_row+1][nr_col]; } } for(i=0;i<n;i++) { sum+=sign*matrix[0][i]*det(minor,n-1); sign = -sign; }; matrix_free(minor, n-1); return sum; } int main(int argc, char** argv) { int rozmiar, x, i=0, j=0; FILE *plik; plik=fopen("macierz.txt", "r"); if(plik==NULL){ cout<<"Podany plik nie istnieje"<<endl; } fscanf(plik, "%d", &rozmiar); printf("\n"); printf("Rozmiar macierzy wynosi: %d x %d\n\n", rozmiar, rozmiar); double** matrix=new double*[rozmiar]; for(x = 0; x<rozmiar; x++){ matrix[x]=new double[rozmiar]; } printf("Nasza macierz: \n"); j=0; while(j<rozmiar){ i = 0; while(i<rozmiar){ fscanf(plik, "%lf", &matrix[i][j]); printf("%.2lf\t", matrix[i][j]); i++; } printf("\n"); ++j; } printf("\n"); printf("Wartosc wyznacznika macierzy wynosi: %lf\n", det(matrix, rozmiar)); fclose(plik); return 0; }
a po kompilacji...
ania@debian:~/Desktop/project$ ./a.out Rozmiar macierzy wynosi: 3 x 3 Nasza macierz: 1.00 2.00 3.00 4.00 5.00 6.00 7.00 8.00 9.00 *** glibc detected *** ./a.out: free(): invalid pointer: 0xb763b4c0 *** ======= Backtrace: ========= /lib/i686/cmov/libc.so.6(+0x6b281)[0xb7564281] /lib/i686/cmov/libc.so.6(+0x6cad8)[0xb7565ad8] /lib/i686/cmov/libc.so.6(cfree+0x6d)[0xb7568bbd] /usr/lib/libstdc++.so.6(_ZdlPv+0x21)[0xb773e701] /usr/lib/libstdc++.so.6(_ZdaPv+0x1d)[0xb773e75d] ./a.out[0x8048a01] ./a.out[0x8048b70] ./a.out[0x8048d36] /lib/i686/cmov/libc.so.6(__libc_start_main+0xe6)[0xb750fc76] ./a.out[0x8048881] ======= Memory map: ======== 08048000-0804a000 r-xp 00000000 08:09 1254409 /home/ania/Desktop/project/a.out 0804a000-0804b000 rw-p 00001000 08:09 1254409 /home/ania/Desktop/project/a.out 08e65000-08e86000 rw-p 00000000 00:00 0 [heap] b7300000-b7321000 rw-p 00000000 00:00 0 b7321000-b7400000 ---p 00000000 00:00 0 b74f7000-b74f9000 rw-p 00000000 00:00 0 b74f9000-b7639000 r-xp 00000000 08:07 636158 /lib/i686/cmov/libc-2.11.2.so b7639000-b763b000 r--p 0013f000 08:07 636158 /lib/i686/cmov/libc-2.11.2.so b763b000-b763c000 rw-p 00141000 08:07 636158 /lib/i686/cmov/libc-2.11.2.so b763c000-b763f000 rw-p 00000000 00:00 0 b763f000-b765c000 r-xp 00000000 08:07 488755 /lib/libgcc_s.so.1 b765c000-b765d000 rw-p 0001c000 08:07 488755 /lib/libgcc_s.so.1 b765d000-b7681000 r-xp 00000000 08:07 636142 /lib/i686/cmov/libm-2.11.2.so b7681000-b7682000 r--p 00023000 08:07 636142 /lib/i686/cmov/libm-2.11.2.so b7682000-b7683000 rw-p 00024000 08:07 636142 /lib/i686/cmov/libm-2.11.2.so b7683000-b776c000 r-xp 00000000 08:07 700747 /usr/lib/libstdc++.so.6.0.13 b776c000-b7770000 r--p 000e9000 08:07 700747 /usr/lib/libstdc++.so.6.0.13 b7770000-b7771000 rw-p 000ed000 08:07 700747 /usr/lib/libstdc++.so.6.0.13 b7771000-b7779000 rw-p 00000000 00:00 0 b778c000-b778f000 rw-p 00000000 00:00 0 b778f000-b7790000 r-xp 00000000 00:00 0 [vdso] b7790000-b77ab000 r-xp 00000000 08:07 284843 /lib/ld-2.11.2.so b77ab000-b77ac000 r--p 0001a000 08:07 284843 /lib/ld-2.11.2.so b77ac000-b77ad000 rw-p 0001b000 08:07 284843 /lib/ld-2.11.2.so bfd90000-bfda5000 rw-p 00000000 00:00 0 [stack] Przerwane
Czo to jest i z czym się je?
Wrzuciłam sobie też kod Huk'a, kompiluje się, liczy wyznacznik, dla 3x3 jakoś 0 pokazuje. Moja koncepcja jest taka, żeby wywalić na ekran ten minor, popatrzeć jak to skopiowało, bo te dwa fory o kant dupy można rozbić. Imo, w ich okolicy się wywala.
Offline
To są bardzo dobry błędy. Skompiluj program z opcją -g i wtedy możesz użyć adresów wypisywanych w tym dumpie w mistycznym programiku, który wyznali linię w kodzie gdzie takowy błąd wyskoczył.
Choć już na oko widać gdzie jest błąd :) "free(): invalid pointer" mówi samo za siebie.
addr2line -f -e ./path/a.out $ADDRESS
gdzie $ADDRESS to ten hex zwracany w dumpie:
./a.out[0x8048a01]
./a.out[0x8048b70]
./a.out[0x8048d36]
...
./a.out[0x8048881]
np. addr2line -f -e a.out 0x8048a01
Jak widzisz masz kilka wskazań przy a.out co jest fajne, bo pokaże Ci drogę która doprowadziła do błędu: np. main() -> xx() --> zz --> detownik()
W miejscu błędów wyprintfuj wyniki pośrednie.
Jeszcze jedna rzecz... Wydziel z det() funcję minor. I printfuj tworzone kompletne minory, by mieć pewność że minory są poprawne.
Ostatnio edytowany przez NIC (2011-11-06 14:32:37)
Offline
Masz wyobraźnię, jeśli myślisz że zrozumiem choć gram z tego co napisałeś :) Wątek bezcelowy bo mam większy mętlik niż miałam..
aaa tam, dzięki ale chyba się poddam.
Offline
*macierz = (double*) calloc(stopien, sizeof(double)); for(int i=0;i<stopien;++i) { macierz[i] = (double*) calloc(stopien, sizeof(double)); }
*macierz = macierz[0]
chcialas chyba macierz = (double **)calloc(...);
I na bogów... nie mieszaj calloc z delete! użyj free() lub new
Offline
Nie wiem co chciałam, bo tak się kończy usilne podsuwanie sposobu który ciężko wpisać w kod.
Nadal nie działa, oddam mniej ambitną wersję, ale działającą.
Offline
Strony: 1