Witam, mam problem z nieszczęsnym sigsegv... Tak, wiem, że ten błąd powodowany jest przez (prawdopodobnie) wyjście poza tablicę jakimś wskaźnikiem albo innym cudem, ale, czy ktoś spotkał się z wyjściem poza tablicę w miejscu, gdzie program się kończy?...
Kompilator: lazarus, język pascal.
Kod:
!! PLIK bazaDanychWskazniki !!
program bazaDanychWskazniki;
uses unit_TOsoba, unit_bazadanych;
var
mojaBaza : wskTOsoba;
i : integer;
begin
utworzBaze(mojaBaza, 2);
wczytajBazeZPliku(mojaBaza, 'pliki/baza.tos');
powiekszBaze(mojaBaza, 1);
wypelnijTOsoba(mojaBaza[6]);
for i:=1 to mojaBaza[0].wiek do
wyswietlTOsoba(mojaBaza[i]);
writeLn('abc');
readLn();
end.
!! PLIK unit_TOsoba !!
unit unit_TOsoba;
interface
type
TOsoba = record
imie:String[16];
nazwisko:String[16];
wiek:integer;
end;
wskTOsoba = ^Tosoba;
procedure wypelnijTOsoba(var osoba : TOsoba);
procedure wyswietlTOsoba(var osoba : TOsoba);
implementation
procedure wypelnijTOsoba(var osoba : TOsoba);
begin
writeLn('Wypelnij dane osobowe...');
write('Imie: ');
readLn(osoba.imie);
write('Nazwisko: ');
readLn(osoba.nazwisko);
write('Wiek: ');
readLn(osoba.wiek);
end;
procedure wyswietlTOsoba(var osoba : TOsoba);
begin
writeLn(osoba.imie:16, '|', osoba.nazwisko:16, '|', osoba.wiek:3);
end;
end.
!! PLIK unit_bazaDanych !!
unit unit_bazadanych;
interface
uses unit_TOsoba;
procedure utworzBaze(var baza : wskTOsoba; const ileUtworzyc : integer);
procedure usunBaze(var baza : wskTOsoba);
procedure powiekszBaze(var baza : wskTOsoba; const oIlePowiekszyc : integer);
procedure wczytajBazeZPliku(var baza : wskTOsoba; const sciezka : string);
procedure zapiszBazeDoPliku(const baza : wskTOsoba; const sciezka : string);
implementation
procedure utworzBaze(var baza : wskTOsoba; const ileUtworzyc : integer);
begin
getMem(baza, sizeOf(baza^) * ileUtworzyc+1);
baza[0].wiek := ileUtworzyc;
end;
procedure usunBaze(var baza : wskTOsoba);
begin
freeMem(baza, sizeOf(baza^) * baza[0].wiek+1);
end;
procedure wczytajBazeZPliku(var baza : wskTOsoba; const sciezka : string);
var
i, rozmiarPliku: integer;
plik : file of TOsoba;
strumienTOsoba : wskTOsoba;
begin
assign(plik, sciezka);
reset(plik);
new(strumienTOsoba);
rozmiarPliku := 0;
while not eof(plik) do
begin
read(plik, strumienTOsoba^);
rozmiarPliku := rozmiarPliku+1;
end;
if (rozmiarPliku > baza[0].wiek ) then
powiekszBaze(baza, (rozmiarPliku - baza[0].wiek) );
reset(plik);
for i:=1 to (baza[0].wiek) do
read(plik, baza[i]);
close(plik);
dispose(strumienTOsoba);
end;
procedure zapiszBazeDoPliku(const baza : wskTOsoba; const sciezka : string);
var
plik : file of TOsoba;
i:integer;
begin
assign(plik, sciezka);
rewrite(plik);
for i:=1 to (baza[0].wiek) do
write(plik, baza[i]);
close(plik);
end;
procedure powiekszBaze(var baza : wskTOsoba; const oIlePowiekszyc : integer);
var
nowaBaza : wskTOsoba;
i : integer;
begin
utworzBaze(nowaBaza, (baza[0].wiek + oIlePowiekszyc));
for i:=1 to (baza[0].wiek) do
begin
nowaBaza[i].imie := baza[i].imie;
nowaBaza[i].nazwisko := baza[i].nazwisko;
nowaBaza[i].wiek := baza[i].wiek;
end;
usunBaze(baza);
baza := nowaBaza;
end;
end.
Okej, jak mamy kod, to teraz najśmieszniejsze... Kompilator wywala SIGSEV po readLn(); w głównym miejscu wykonywania programu, czyli w pliku bazaDanychWskazniki (tym 1.). Kiedy uruchamiam program z .exe'ka, wywala runtime errory 216 w konsoli dokladnie w tym samym miejscu (linijka writeLn('abc') umieszczona w celu debugowania...). Tak, debugowałem program krok po kroku i sigseva + runtime'y wywala dopiero po tym readLn();...
Problem pojawił się kiedy dodałem linijkę powiekszBaze(mojaBaza, 1) i wypełniłem nowy rekord... bez tych dwóch linijek kod działa bez zarzutu.
Celowo z kodu usunąłem procedurę zwalniającą pamięć po bazie (usunBaze), której używałem na końcu programu, ale niestety dzieje się to samo (myślałem, że to ona wychodzi poza zakres).
Czy ktoś miał takie przykre doświadczenia i wie, jak z tego wybrnąć?
Pozdrawiam, Rosumad.