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



Wredotka




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



Administrator




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



Wredotka




Z tym tak - miałeś rację, ale nadal się wywala. Problem tkwi chyba w kopiowaniu elementów jednej macierzy do drugiej.
Offline



Administrator




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



Smoleńsk BULWA!




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


prawie jak admin



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



Wredotka




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


prawie jak admin



Trin to daj teraz cały kod jaki masz :) żebyśmy puzzli nie składali
Offline



Wredotka




Teraz ten kod wywala jakiś armagedon w konsoli. Ja mam dość :<
Offline



Smoleńsk BULWA!




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



Wredotka




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


Członek DUG
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



Wredotka




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



inż.
*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



Wredotka




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