Forum AmigaOne Zone

Forum użytkowników Amigi i nie tylko
Teraz jest niedziela, 25 cze 2017, 19:23

Strefa czasowa: UTC + 1 [ DST ]




Utwórz nowy wątek Odpowiedz w wątku  [ Posty: 44 ]  Przejdź na stronę Poprzednia strona  1, 2, 3
Autor Wiadomość
PostNapisane: sobota, 25 lut 2017, 22:54 
Offline
Aktywny forumowicz
Aktywny forumowicz
Avatar użytkownika

Dołączył(a): piątek, 20 sty 2012, 06:09
Posty: 297
tchomasz napisał(a):
Poniżej załączam moje wypociny z podmianą tagów - nie będę wklejał bo niezły tasiemiec z tego wyjdzie. Powiązałem pozycję okna z rozdzielczością ekranu, oraz pozycję filerequestera z rozdzielczością okna.
Teraz zacząłem dłubać przy obsłudze plików.
Za pomocą funkcji Examine() wyciągam sobie rozmiar pliku. Czy da się zarezerwować obszar pamięci dla funkcji Read(), w którym mają być odczytane dane z pliku za pomocą tego wyciągniętego rozmiaru - mam nadzieję że nie zamotałem. Chodzi o to, żeby odczytując plik dane były zapisywane do bufora o wielkości identycznej jak wielkość pliku.

Oczywiście. Rezerwujesz pamięć za pomocą funkcji biblioteki exec do alokacji pamięci, np.: AllocMem(), AllocVec(). Jako argument podaj rozmiar pliku, czyli wartość odpowiedniego pola ze struktury FileInfoBlock. Pamiętaj by zwolnić tą pamięć gdy nie jest już potrzebna za pomocą analogicznej funkcji do zwalniania pamięci: FreeMem(), FreeVec().


Udostępnij dla FacebookUdostępnij dla TwitterUdostępnij dla Google+
Góra
 Zobacz profil  
Cytuj  
PostNapisane: niedziela, 26 lut 2017, 01:27 
Offline
Administrator
Administrator

Dołączył(a): poniedziałek, 16 sty 2012, 14:40
Posty: 170
Lokalizacja: okolice Lublina
Napisałem coś takiego - dopisane do poprzedniego kodu.


Kod:
static int BadaniePliku(void);

char *plik;
int rozmiar;
char *zawartosc;
long read;


Kod:
static int BadaniePliku(void)
{
    BPTR in, check;
    char ch;
    struct FileInfoBlock *fib;
    if (fib=AllocVec(sizeof(struct FileInfoBlock), MEMF_ANY))
    {
        if (check = Lock(plik, SHARED_LOCK))
        {
            printf("Plik %s zostal zablokowy dla innych.\n", plik);
            if(Examine(check, fib))
            {
                rozmiar = fib->fib_Size;
                printf("Plik %s ma rozmiar %d bajtow.\n", plik, rozmiar);
            }
            else
            {
                PrintFault(IoErr(), "Examine");
                FreeVec(fib);
                return 0;
            }
            UnLock(check);
        }
        else
        {
            PrintFault(IoErr(), plik);
            FreeVec(fib);
            return 0;
        }
        FreeVec(fib);
    }
    else
    {
        PrintFault(ERROR_NO_FREE_STORE, "AllocMem - Examine");
        return 0;
    }
    if (in = Open(plik, MODE_OLDFILE))          //otwarcie pliku
    {
        if (zawartosc=AllocVec(rozmiar, MEMF_ANY))
        {
            if ((read = Read(in, zawartosc, rozmiar))==-1)
            {
                PrintFault(IoErr(), "Blad odczytu");
                FreeVec(zawartosc);
                Close(in);
                return 0;
            }
            else
            {
                printf("Ilosc przeczytanych bajtow %d\n", read);
            }
            FreeVec(zawartosc);
        }
        else
        {
            PrintFault(ERROR_NO_FREE_STORE, "AllocMem - open file");
            Close(in);
            return 0;
        }
    }
    else
    {
        PrintFault(IoErr(), "Otwarcie pliku");
        return 0;
    }
    Close(in);
}


Niby działa, ale mile widziane uwagi.


Góra
 Zobacz profil  
Cytuj  
PostNapisane: środa, 1 mar 2017, 23:52 
Offline
Administrator
Administrator

Dołączył(a): poniedziałek, 16 sty 2012, 14:40
Posty: 170
Lokalizacja: okolice Lublina
Program mi wywala błąd.
Załącznik:
blad.png
blad.png [ 11.85 KiB | Przeglądane 346 razy ]


Poniżej część kodu - całość w załączniku poniżej.
Wczytanie pliku mam powiązane z menu 'Open', zapis z 'Save as'. Przy zapisie tworzy mi plik o wybranej nazwie, zapisuje w nim 'zawartosc' i wywala błąd. O co mu chodzi?

Kod:
                            struct MenuItem *item=ItemAddress(menu, Code);
                            if (Code==FULLMENUNUM(0, 0, NOSUB))
                                {
                                    FileReq(ASLHailRead, ASLOKTextRead);
                                    if (BadaniePliku()==NULL)
                                        {
                                            printf("Nie udalo sie wczytac pliku.\n");
                                        }
                                        else
                                        {
                                            OpenFile();
                                        }
                                }
                            if (Code==FULLMENUNUM(0, 3, NOSUB))
                                {
                                    FileReq(ASLHailWrite, ASLOKTextWrite);
                                    WriteFile();
                                }


Kod:
static int BadaniePliku(void)
{
    BPTR check;
    struct FileInfoBlock *fib;
    if (fib=AllocVec(sizeof(struct FileInfoBlock), MEMF_PUBLIC))
    {
        if (check = Lock(plik, SHARED_LOCK))
        {
            printf("Plik %s zostal zablokowy dla innych.\n", plik);
            if(Examine(check, fib))
            {
                rozmiar = fib->fib_Size;
                printf("Plik %s ma rozmiar %d bajtow.\n", plik, rozmiar);
            }
            else
            {
                PrintFault(IoErr(), "Examine");
                FreeVec(fib);
                return 0;
            }
            UnLock(check);
        }
        else
        {
            PrintFault(IoErr(), plik);
            FreeVec(fib);
            return 0;
        }
        FreeVec(fib);
    }
    else
    {
        PrintFault(ERROR_NO_FREE_STORE, "AllocMem - Examine");
        return 0;
    }
}

static int OpenFile(void)
{
    BPTR in;
    if (in = Open(plik, MODE_OLDFILE))          //otwarcie pliku
    {
        if (zawartosc=AllocVec(rozmiar, MEMF_PUBLIC))
        {
            if ((read = Read(in, zawartosc, rozmiar))==-1)
            {
                PrintFault(IoErr(), "Blad odczytu");
                FreeVec(zawartosc);
                Close(in);
                return 0;
            }
            else
            {
                printf("Ilosc przeczytanych bajtow %d\n", read);
            }
//          FreeVec(zawartosc);
        }
        else
        {
            PrintFault(ERROR_NO_FREE_STORE, "AllocMem - open file");
            Close(in);
            return 0;
        }
    }
    else
    {
        PrintFault(IoErr(), "Otwarcie pliku");
        return 0;
    }
    Close(in);
}

static int WriteFile(void)
{
    BPTR out;
    if (out = Open(plik, MODE_NEWFILE))
    {
        if ((write = Write(out, zawartosc, rozmiar))==-1)
        {
            PrintFault(IoErr(), "Blad zapisu");
            FreeVec(zawartosc);
            Close(out);
            return 0;
        }
        else
        {
            printf("Ilosc zapisanych bajtow %d\n", write);
        }
        FreeVec(zawartosc);
    }
    else
    {
        PrintFault(IoErr(), "Otwarcie pliku - zapisz jako");
        return 0;
    }
    Close(out);
}



Załączniki:
menu_test2.c [8.44 KiB]
Pobrane 11 razy
Góra
 Zobacz profil  
Cytuj  
PostNapisane: czwartek, 2 mar 2017, 01:45 
Offline
Aktywny forumowicz
Aktywny forumowicz
Avatar użytkownika

Dołączył(a): piątek, 20 sty 2012, 06:09
Posty: 297
Przyjrzałem się załączonemu kodowi źródłowemu.

Zauważyłem, że w funkcji zapisu WriteFile() nie rezerwujesz pamięci. Wskaźnik zawartość nie jest przypisany do żadnej zaalokowanej pamięci! A próbujesz zapisać w pliku część pamięci o rozmiarze rozmiar spod tego wskaźnika. Jest to nielegalne.

Dodatkowo próbujesz zwolnić pamięć spod tego adresu za pomocą FreeVec() bez uprzedniej alokacji.

Teraz pytanie: co chcesz w tym pliku zapisać?


Góra
 Zobacz profil  
Cytuj  
PostNapisane: czwartek, 2 mar 2017, 11:33 
Offline
Administrator
Administrator

Dołączył(a): poniedziałek, 16 sty 2012, 14:40
Posty: 170
Lokalizacja: okolice Lublina
To po kolei. Mam dwie funkcje OpenFile i WriteFile, obie są podpięte pod menu. Wszystkie testy robię na jednym przykładowym pliku. Klikając w menu Open wybieram mój przykładowy plik. Badam go funkcją BadaniePliku, aby ustalić jego wielkość i w funkcji OpenFile allokuję tyle pamięci co wielkość pliku. Później odczytuję plik i to co odczytam przechowuję w 'zawartosc'. Nie robię FreeVec(zawartosc) w OpenFile, po to aby to co odczytałem z pliku w kosmos mi nie poszło i żebym mógł w funkcji WriteFile z tego skorzystać. Klikając w menu Save as wybieram pod jaką nową nazwą ma być zapisany mój plik. Później 'zawartosc' kopiuję do tego pliku i wtedy mi wywala błąd. Generalnie chciałem na razie sobie przetestować otwarcie i odczyt pliku, a później bez jakiejkolwiek zmiany zapis do nowego pliku.
Dlatego w funkcji WriteFile nie allokuję pamięci tylko chciałem skorzystać z zaalokowanej w funkcji OpenFile - czy tak można zrobić?


Góra
 Zobacz profil  
Cytuj  
PostNapisane: czwartek, 2 mar 2017, 14:46 
Offline
Aktywny forumowicz
Aktywny forumowicz
Avatar użytkownika

Dołączył(a): piątek, 20 sty 2012, 06:09
Posty: 297
OK.

Na początek ważna kwestia. Chcę wykluczyć jedną ewentualność. Strukturę FileInfoBlock warto zaalokować za pomocą funkcji AllocDosObject(DOS_FIB, NULL) z biblioteki dos. Nie wiem, czy o to chodzi, ale warto to poprawić. Zwalniasz za pomocą FreeDosObject(DOS_FIB, fib).

Mam pytanie: jakiego używasz kompilatora? Ten numer "Software Failure" oznacza nielegalny dostęp do pamięci (możesz o tym poczytać w pliku załącznikowym exec/alerts.h). Może mieć to związek z kompilatorem.

Nie zauważyłem znaku komentarza przy FreeVec() w funkcji OpenFile().

Teoretycznie Twój kod powinien zadziałać, kiedy wywołasz najpierw "Open", a później "Save". Jednakże konstrukcja Twojego programu jest niefortunna. W przypadku gdy np. użytkownik od razu wybierze "Save" program się wysypie z podanego w poprzednim poście powodu.

Polecam zmienić funkcję WriteFile(), by pobierała jako parametr co ma zapisać i ile bajtów ma zapisać, np. tak:
int WriteFile(char *zawartosc, long rozmiar);

Zaś jeśli chodzi o funkcję BadaniePliku() i OpenFile(), to polecam zrobić tak:
  • W funkcji BadaniePliku() pobrać rozmiar i zwrócić (czyli tak jak jest teraz),
  • W funkcji OpenFile() zarezerwować pamięć, wczytać i zwrócić adres pamięci,
  • Dorobić funkcję CloseFile(), w której zwalniasz pamięć zaalokowaną przez OpenFile().
  • Usunąć z funkcji WriteFile() zwalnianie pamięci.

EDIT: U mnie program działa, nie wysypuje się. Obstawiam kompilator.


Góra
 Zobacz profil  
Cytuj  
PostNapisane: czwartek, 2 mar 2017, 23:01 
Offline
Administrator
Administrator

Dołączył(a): poniedziałek, 16 sty 2012, 14:40
Posty: 170
Lokalizacja: okolice Lublina
Hextreme napisał(a):
EDIT: U mnie program działa, nie wysypuje się. Obstawiam kompilator.


Ale kompilowałeś w nie zmienianej wersji?

Ja używam gcc 2.95.3 - ze strony kas1e'a, którą podał swinkamor12 w innym wątku. Do tej pory mi wszystko działało. Testuję pod WinUAE.


Góra
 Zobacz profil  
Cytuj  
PostNapisane: czwartek, 2 mar 2017, 23:58 
Offline
Aktywny forumowicz
Aktywny forumowicz
Avatar użytkownika

Dołączył(a): piątek, 20 sty 2012, 06:09
Posty: 297
Gwoli ścisłości zmieniłem tylko jedną rzecz, która jednak nie odgrywa tutaj żadnej roli. Zmienną "write" uczyniłem lokalną. Nie wiem czemu, ale linker mi marudził.

Poza tym nic w kodzie nie zmieniałem. Użyłem kompilatora DICE.


Góra
 Zobacz profil  
Cytuj  
PostNapisane: piątek, 3 mar 2017, 23:13 
Offline
Administrator
Administrator

Dołączył(a): poniedziałek, 16 sty 2012, 14:40
Posty: 170
Lokalizacja: okolice Lublina
Jak możesz to wklej skompilowany program, to zobaczę czy pod WinUAE mi się wysypie.


Góra
 Zobacz profil  
Cytuj  
PostNapisane: sobota, 4 mar 2017, 00:46 
Offline
Aktywny forumowicz
Aktywny forumowicz
Avatar użytkownika

Dołączył(a): piątek, 20 sty 2012, 06:09
Posty: 297
Proszę.

Do kodu musiałem tylko załączyć <exec/memory.h> bo nie rozpoznawał symbolu MEMF_PUBLIC. Czy na pewno wersja kodu, którą wkleiłeś jest najbardziej aktualna?


Załączniki:
Komentarz: Program MenuTest skompilowany pod DICE.
MenuTest_DICE.lha [5.61 KiB]
Pobrane 8 razy
Góra
 Zobacz profil  
Cytuj  
PostNapisane: sobota, 4 mar 2017, 07:55 
Offline
Elitarny forumowicz
Elitarny forumowicz

Dołączył(a): wtorek, 17 sty 2012, 18:21
Posty: 734
Parę poprawek:

1. Zmienne read i write jak Robert pisał warto zrobić jako lokalne
2. Brakowało otwarcia i zamknięcia utility library
3. Przy otwarciu okna lepiej nie podawać maksymalnych wymiarów jak są nie używane
usunięte:
WA_MaxWidth, -1,
WA_MaxHeight, -1,
4. zmienna plik - to jest wskaźnik, pamięć po wywołaniu FreeAslRequest może zostać zwolniona i będą tam śmiecie
trzeba przepisać zawartość. Warto też pobrać katalog - będzie można obsługiwać pliki też spoza aktulanego katalogu.

char plik[1000];

memset(plik,0,sizeof(plik));
strncpy(plik,fr->rf_Dir, sizeof(plik)-1 );
AddPart( plik, fr->rf_File, sizeof(plik)-1 );


Załączniki:
menu_test2.zip [10.04 KiB]
Pobrane 6 razy
Góra
 Zobacz profil  
Cytuj  
PostNapisane: sobota, 4 mar 2017, 18:27 
Offline
Administrator
Administrator

Dołączył(a): poniedziałek, 16 sty 2012, 14:40
Posty: 170
Lokalizacja: okolice Lublina
Hextreme napisał(a):
Proszę.

Do kodu musiałem tylko załączyć <exec/memory.h> bo nie rozpoznawał symbolu MEMF_PUBLIC. Czy na pewno wersja kodu, którą wkleiłeś jest najbardziej aktualna?

Działa bez problemu.

Wysłane z mojego GT-I9300 przy użyciu Tapatalka


Góra
 Zobacz profil  
Cytuj  
PostNapisane: sobota, 4 mar 2017, 18:30 
Offline
Administrator
Administrator

Dołączył(a): poniedziałek, 16 sty 2012, 14:40
Posty: 170
Lokalizacja: okolice Lublina
swinkamor12 napisał(a):
Parę poprawek:

1. Zmienne read i write jak Robert pisał warto zrobić jako lokalne
2. Brakowało otwarcia i zamknięcia utility library
3. Przy otwarciu okna lepiej nie podawać maksymalnych wymiarów jak są nie używane
usunięte:
WA_MaxWidth, -1,
WA_MaxHeight, -1,
4. zmienna plik - to jest wskaźnik, pamięć po wywołaniu FreeAslRequest może zostać zwolniona i będą tam śmiecie
trzeba przepisać zawartość. Warto też pobrać katalog - będzie można obsługiwać pliki też spoza aktulanego katalogu.

char plik[1000];

memset(plik,0,sizeof(plik));
strncpy(plik,fr->rf_Dir, sizeof(plik)-1 );
AddPart( plik, fr->rf_File, sizeof(plik)-1 );

Dzieki za uwagi. W wolnej chwili porobię poprawki.

Wysłane z mojego GT-I9300 przy użyciu Tapatalka


Góra
 Zobacz profil  
Cytuj  
PostNapisane: niedziela, 5 mar 2017, 03:45 
Offline
Administrator
Administrator

Dołączył(a): poniedziałek, 16 sty 2012, 14:40
Posty: 170
Lokalizacja: okolice Lublina
Wystarczyło, że tylko zmienne read i write zmieniłem na lokalne i przestało się wywalać.

utility.library dopisane, WA_MAX wywalone, zmiennej plik jeszcze nie ruszałem.


Góra
 Zobacz profil  
Cytuj  
Wyświetl posty nie starsze niż:  Sortuj wg  
Utwórz nowy wątek Odpowiedz w wątku  [ Posty: 44 ]  Przejdź na stronę Poprzednia strona  1, 2, 3

Strefa czasowa: UTC + 1 [ DST ]


Kto przegląda forum

Użytkownicy przeglądający ten dział: Brak zidentyfikowanych użytkowników i 1 gość


Nie możesz rozpoczynać nowych wątków
Nie możesz odpowiadać w wątkach
Nie możesz edytować swoich postów
Nie możesz usuwać swoich postów
Nie możesz dodawać załączników

Szukaj:
Skocz do:  
Powered by phpBB® Forum Software © phpBB Group
Przyjazne użytkownikom polskie wsparcie phpBB3 - phpBB3.PL
phpBB SEO