Problem ze wskaźnikami - RE 216

0

Witam! Mam problem ze wskaźnikami, a konkretniej uruchomienie programu kończy się RE 216. Co prawda odnalazłem miejsce, gdzie prawdopodobnie jest problem, lecz ja go tam nie widzę. Poświęciłem na to ponad 4 godziny, ale nie udało mi się tego naprawić. Z góry dzięki za pomoc.

W załączniku cały kod programu - trochę tego jest ponad 500 linii oraz wynik konsoli.

1

Poświęciłem na to ponad 4 godziny, ale nie udało mi się tego naprawić.

No widzisz bo nie wpadłeś na użycie DEBUGGERa.
Zresztą o ile korzystasz z FPC to po chwili googlowania byś znalazł że musisz użyć modułu sysutils. Dodatkowo włącz sobie generowanie linii w zrzucie i jeżeli po użyciu DEBUGGERa nie będziesz mieć pomysłów to wrzuć call stack, zmienne, kawałki kodu oraz eksperymenty jakie przeprowadziłeś.

0

Racja zapomniałem o DEBUGGERze. Dzięki za przypomnienie. Niemniej jednak ustaliłem, że błąd powoduje linijka 158 i komunikat to Program received signal SIGSEGV, Segmentation fault. Z tego co wiem to ten błąd oznacza naruszenie ochrony pamięci, polegające na korzystaniu przez program z pamięci poza zaalokowanym dla niego obszarem. Ale nie za bardzo wiem jak to się ma do mojego programu, bo element do którego się odwołuje na pewno istnieje i miał zaalokowaną pamięć, bo inaczej by nie przeszedł warunku chwilę wcześniej w pętli while:

156: while (t <> nil) and (not found) do
157:    begin
158:       if (t^.name <> s) then

chyba, że się mylę.

I nie wiem co miałoby zmienić dodanie modułu sysutils. Wiem tylko, że może obsługiwać wyjątki, ale raczej nie do końca rozumiem jakby to miało działać. Wyjaśnij proszę, jeśli możesz. :)

W załączniku call stack i okno z komunikatem, które mi wyskoczyło przy odpalaniu zadania pod linuksem.

1

I nie wiem co miałoby zmienić dodanie modułu sysutils. Wiem tylko, że może obsługiwać wyjątki, ale raczej nie do końca rozumiem jakby to miało działać. Wyjaśnij proszę, jeśli możesz.

Po prostu dodaj, nie będziesz otrzymywać 217 (nieznany błąd) dzięki temu tylko dokładniejszy kod błędu.

1.Nie używa się konstrukcji pointer<>nil tylko assigned(pointer), gdyż jest to szybsze.
2.Żeby otrzymać SIGSEGV pointer wcale nie musi być null, wystarczy że się odwołuje do miejsca które jest niepoprawne.
3.Z call stack wynika że FPC wywala się podczas porównania stringów więc zapewne t^.name nie jest poprawne.
4.Listy jedno/dwukierunkowe są bardzo podatne na błędy, najlepiej przerzuć się na coś w stylu dynamic array, albo w sumie to można też na TStringList.

0

Ok. Dzięki wielkie za rady i wyjaśnienia. Przeanalizuję jeszcze raz tworzenie tego t^.name - może coś gdzieś mi po prostu umknęło. Co do dynamic array to chętnie bym takiej użył, ale niestety wymogami zadania jest zrobienie tego na wskaźnikach. Niemniej jednak dzięki za sugestie. :)

1

Co do dynamic array to chętnie bym takiej użył, ale niestety wymogami zadania jest zrobienie tego na wskaźnikach

To ja bym napisał klasę odpowiadającą za listę, przetestował ją i się nie martwił. No chyba że klas też nie możesz używać (roftlol). W każdym razie w kodzie póki co masz niezły bałagan.

Co do punktu 1 to nie wiem dlaczego test eax, eax ma być szybsze od test eax, eax bo do tej instrukcji sprowadza się zarówno assigned jak i porównanie z nil

Gdzieś tak przeczytałem w dokumentacji/wiki FPC ale nie mogę tego znaleźć. W każdym razie wygląda to ładniej a wolniejsze nie jest.

BTW.
program zadanie4;//kosultacje wtorek 15:45 - 17:00 :-]

0

W klasach jeszcze niezbyt pewnie się czuję, więc nie próbowałem ich tutaj wprowadzać, ale prawdopodobnie mógłbym je tutaj wprowadzić. A w kodzie to rzeczywiście mam bałagan. Będę musiał to jakoś ogarnąć.

Odnalazłem w czym był problem. Zwyczajnie zapomniałem ustawić wskaźników nowo tworzonej komórki na nil. Chociaż wydaje mi się, że powinny automatycznie być nill'owane. Jak widać jestem w błędzie.
Cóż dzięki wielkie za pomoc.

0

Cóż dzięki wielkie za pomoc.

Zaznacz post który rozwiązał problem 'ptaszkiem' i możesz dać plusy dla postów które pomogły.

1 użytkowników online, w tym zalogowanych: 0, gości: 1