Forum AmigaOne Zone
https://forum.amigaone.pl/

Programowanie pod AmigaOS 3.1 - kilka pytań.
https://forum.amigaone.pl/programowanie-f13/programowanie-pod-amigaos-3-1-kilka-pytan-t935-30.html
Strona 3 z 4

Autor:  Hextreme [ sobota, 25 lut 2017, 21:54 ]
Tytuł:  Re: Programowanie pod AmigaOS 3.1 - kilka pytań.

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().

Autor:  tchomasz [ niedziela, 26 lut 2017, 00:27 ]
Tytuł:  Re: Programowanie pod AmigaOS 3.1 - kilka pytań.

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.

Autor:  tchomasz [ środa, 1 mar 2017, 22:52 ]
Tytuł:  Re: Programowanie pod AmigaOS 3.1 - kilka pytań.

Program mi wywala błąd.
Załącznik:
blad.png


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);
}


Autor:  Hextreme [ czwartek, 2 mar 2017, 00:45 ]
Tytuł:  Re: Programowanie pod AmigaOS 3.1 - kilka pytań.

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ć?

Autor:  tchomasz [ czwartek, 2 mar 2017, 10:33 ]
Tytuł:  Re: Programowanie pod AmigaOS 3.1 - kilka pytań.

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ć?

Autor:  Hextreme [ czwartek, 2 mar 2017, 13:46 ]
Tytuł:  Re: Programowanie pod AmigaOS 3.1 - kilka pytań.

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.

Autor:  tchomasz [ czwartek, 2 mar 2017, 22:01 ]
Tytuł:  Re: Programowanie pod AmigaOS 3.1 - kilka pytań.

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.

Autor:  Hextreme [ czwartek, 2 mar 2017, 22:58 ]
Tytuł:  Re: Programowanie pod AmigaOS 3.1 - kilka pytań.

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.

Autor:  tchomasz [ piątek, 3 mar 2017, 22:13 ]
Tytuł:  Re: Programowanie pod AmigaOS 3.1 - kilka pytań.

Jak możesz to wklej skompilowany program, to zobaczę czy pod WinUAE mi się wysypie.

Autor:  Hextreme [ piątek, 3 mar 2017, 23:46 ]
Tytuł:  Re: Programowanie pod AmigaOS 3.1 - kilka pytań.

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?

Autor:  swinkamor12 [ sobota, 4 mar 2017, 06:55 ]
Tytuł:  Re: Programowanie pod AmigaOS 3.1 - kilka pytań.

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 );

Autor:  tchomasz [ sobota, 4 mar 2017, 17:27 ]
Tytuł:  Re: Programowanie pod AmigaOS 3.1 - kilka pytań.

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

Autor:  tchomasz [ sobota, 4 mar 2017, 17:30 ]
Tytuł:  Re: Programowanie pod AmigaOS 3.1 - kilka pytań.

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

Autor:  tchomasz [ niedziela, 5 mar 2017, 02:45 ]
Tytuł:  Re: Programowanie pod AmigaOS 3.1 - kilka pytań.

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.

Autor:  tchomasz [ sobota, 28 paź 2017, 23:42 ]
Tytuł:  Re: Programowanie pod AmigaOS 3.1 - kilka pytań.

Odkopuję trochę temat.

Jak pobrać z systemu aktualną godzinę i datę?

Strona 3 z 4 Strefa czasowa: UTC + 1
Powered by phpBB® Forum Software © phpBB Group
https://www.phpbb.com/