FPC/Lazarus-ban random SIGSEGV errorokat kapok a class-jaimra. Pedig jól néznek ki a Complier se szól, csak amikor futnia kéne akkor meghal. Mi lehet a probléma?
példának okáért itt is van egy egszerűbb:
type Tsettings=class
values:array of array[0..2] of string;
loaded:boolean;
function get(mit:string):string;
function isSet(mit:string):boolean;
constructor load(filepath:string);
end;
function Tsettings.get(mit:string):string;
var i: word;
fund:boolean;
begin
if loaded then
begin
i:=low(values);
fund:=false;
Repeat
if Upcase(values[i,1]) = Upcase(mit) then fund:=True
else inc(i);
until fund or (i = High(values));
if fund then get:=values[i,2]
else get:='Error: 1';
end else get:='Error: 2';
end;
ha futnia kéne meghal, az "if loaded then" soron, ha kiveszem akkor pedig az "if Upcase(values[i,1]) = Upcase(mit) then fund:=True" soron
de itt egy másik is:
type
particles=class
may,miy:single;
pos:TVector3f; // ez egy típus amiben van egy x egy y és egy z ami single
speed:single;
constructor createfalling(py,ly,pspeed:single);
procedure update;
procedure render;
end;
procedure particles.update;
begin
if pos.y < miy then
begin
pos.x:=Random(512)-256;
pos.z:=Random(512)-256;
pos.y:=may;
end else begin
pos.y:=pos.y-speed;
end;
end;
itt pedig az "if pos.y < miy then" soron hal be.
úgy néz ki mintha az if-eken halna be, de más classok is vannak if-ekkel, és azok mennek, a másik meg hogy a class belső változóitól, de ugyanúgy, mások mennek vele.
a SIGSEGVről ezt találtam:
SIGSEGV = Segmentation Fault = Access Violation under Win
Common causes are;
-> miscalculating array ranges in your loops,
-> accessing objects when not created,
-> or just plain and simple trying to access memory that was not allocated for use.
nincs valakinek bármi építő ötlete, mert ez egy nagyon bosszantó error, amivel nem tudok mit kezdeni :(
Az if-ekben vizsgált változók kapnak értéket valamikor a vizsgálat előtt?
Az ide bemásolt kódod nekem nem tűnik hibásnak, nem tudnál inkább egy rövid programot összedobni, ami hozza a hibát?
Igenis :)
itt is van(nak):
type:
Tsettings=class
values:array of array[0..2] of string;
loaded:boolean;
function get(mit:string):string;
function isSet(mit:string):boolean;
constructor load(filepath:string);
end;
constructor Tsettings.load(filepath:string);
var line:string;
resetok:boolean;
i:byte;
fv:textfile;
begin
if FileExists(filepath) then
begin
{$i-}
Assign(fv,filepath);
i:=1;
resetok:=false;
// probalkozas a megnyitassal
Repeat
reset(fv);
if ioresult = 0 then resetok:=True
else inc(i);
until (resetok) or (i = 30);
// ha sikerult
if resetok then
begin
i:=1;
While NOT eof(fv) do
Begin
Readln(fv,line);
if NOT(copy(line,1,2) = '//') then
begin
setlength(values,i);
values[i-1,1]:=Upcase(copy(Line,1,pos('=',Line)-1));
values[i-1,2]:=copy(Line, pos('=',Line)+1 , Length(line)-pos('=',Line)+1);
inc(i);
end;
end;
// ha vegzett az olvasassal
closefile(fv);
loaded:=True;
end else loaded:=False;
end else loaded:=False;
{$i+}
end;
function Tsettings.isSet(mit:string):boolean;
var i:longint;
fund:boolean;
begin
if loaded then
begin
i:=low(values);
fund:=false;
Repeat
if Upcase(values[i,1]) = Upcase(mit) then fund:=True
else inc(i);
until fund or (i = High(values));
if fund then isSet:=true
else isSet:=False;
end else isSet:=False;
end;
function Tsettings.get(mit:string):string;
var i: word;
fund:boolean;
begin
if loaded then
begin
i:=low(values);
fund:=false;
Repeat
if Upcase(values[i,1]) = Upcase(mit) then fund:=True
else inc(i);
until fund or (i = High(values));
if fund then get:=values[i,2]
else get:='Error: 1';
end else get:='Error: 2';
end;
és itt hajtom végre:
settings.load(modname + '\scripts\settings.cfg');
InitOpenglwindow(strtoint(settings.get('width')),strtoint(settings.get('Height')),strtoint(settings.get('posx')),strtoint(settings.get('posy')), settings.get('caption'));
és itt a file is ha kell:
// ablak bealitasok
width=600
height=800
posX=10
posY=10
caption=Testmod
// eddig
fov=75
sensitivy=0.1
caption=Testmod
és itt az error, ha a Lazarusból futtatom:
Project main raised exception class 'External: SIGSEGV'
In File 'file_routines.pas' at line 93:
if loaded then
és itt van ha "magába" fut
An unhandled exception occured at $0041D12F :
EAcessViolation: Acess violation
$0041D12F TSETTINGS__GET, line 93 of file_routines.pas
$00401702 INIT, line 46 of main.lpr
$0040182D main, line 66 of main.lpr
ezek a sorok pedig a main.lpr-ből:
46: InitOpenglwindow(strtoint(settings.get('width')),strtoint(settings.get('Height')),strtoint(settings.get('posx')),strtoint(settings.get('posy')), settings.get('caption'));
66: if NOT INIT then halt;
az előbb emlétett init pedig:
function INIT:boolean;
Begin
// mod ellenorzese
if paramcount = 1 then
Begin
if isModExists(ParamStr(1)) then modname:=ParamStr(1)
else modname:='';
end else modname:='';
// mod betoltese
if modname <> '' then
begin
settings.load(modname + '\scripts\settings.cfg');
InitOpenglwindow(strtoint(settings.get('width')),strtoint(settings.get('Height')),strtoint(settings.get('posx')),strtoint(settings.get('posy')), settings.get('caption'));
beep;
//render cuccok
glutDisplayFunc(@Rendertowindow);
glutIdleFunc(@IDLE);
INIT:=True;
end else INIT:=False;
End;
egyszerűen nem jövök rá, hol lehet a hiba
function INIT:boolean;
Begin
[...]
settings.load(modname + '\scripts\settings.cfg');
[...]
End;
A load ugye a TSettings osztályod konstruktora, a Settings változód gondolom TSettings típusú. Amikor létrehozod az objektumot nem valami ilyesminek kellene lenni a kódnak:
Settings:=TSettings.Load(modname + '\scripts\settings.cfg');
Örülök, hogy segítettem :). Nem tudom a másik módszerrel miért működött a kód, szerintem nem kellett volna neki.
Ha nem veszed zokon lenne még egy két javaslatom. Mivel a konfigurációs fájlban ilyen név érték párok vannak (width=600), így nem muszáj végig zongoráznod, mint egy szövegfájlt. Használhatsz StringListet ( [link] ), ami kezeli ezt (Names és Value property), vagy talán mégjobb ha a TIniFile ( [link] ) objektumot használod.
Kicsit átírtam a TSettings osztályodat, hogy a TIniFile segítségével lehessen beolvasni a cfg fájlodból adatot, illetve visszaírni is lehessen vele.
A cfg fájl nézzen ki így (lévén az ini fájlok valahogy így épülnek fel):
[Windows settigns]
width=600
height=800
posX=10
posY=10
caption=Testmod
[other]
fov=75
sensitivy=0.1
caption=Testmod
A TSettings osztályod pedig lehet ilyen:
unit Unit1;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils, InifFiles;
type
TSettings=Class
private
fWidth: integer;
fHeight: integer;
fPosX: integer;
fPosY: integer;
fCaption: string;
fLoaded: boolean;
fFilePath: string;
procedure SetWidth(aWidth:integer);
procedure SetHeight(aHeight:integer);
procedure SetPosX(aPosX:integer);
procedure SetPosY(aPosY:integer);
procedure SetCaption(aCaption: string);
procedure SetFilePath(aFilePath:string);
public
constructor Create(FilePath:string);
constructor Create(aWidth, aHeight, aPosX,aPosY: integer; aCaption: string);
procedure SaveSettings(FilePath: string);
procedure SaveSettings();
property Width: integer read fWidth write SetWidth;
property Height: integer read fHeight write SetHeight;
property PosX: integer read fPosX write SetPosX;
property PosY: integer read fPosY write SetPosY;
property Caption: string read fCaption write SetCaption;
property FilePath: string read fFilePath write SetFilePath;
property IsLoaded: boolean read fLoaded;
end;
implementation
constructor TSettings.Create(aFilePath:string);
var
ConfigFile: TIniFile;
begin
fLoaded:=False;
if FileExists(aFilePath) then
begin
try
try
ConfigFile:=TIniFile.Create(aFilePath);
except
on EInOutError do writeln('File can not be open!');
end;
fFilePath:=aFilePath;
fWidth:=StrToInt(ConfigFile.ReadString('Windows settings','width','-1'));
fHeight:=StrToInt(ConfigFile.ReadString('Windows settings','height','-1'));
fPosX:=StrToInt(ConfigFile.ReadString('Windows settings','posX','-1'));
fPosY:=StrToInt(ConfigFile.ReadString('Windows settings','posY','-1'));
fCaption:=ConfigFile.ReadString('Windows settings','caption','Default');
fLoaded:=True;
finally
ConfigFile.Free;
end;
end;
end;
constructor TSettings.Create(aWidth, aHeight, aPosX, aPosY: integer; aCaption: string);
begin
fWidth:=aWidth;
fHeight:=aHeight;
fPosX:=aPosX;
fPosY:=aPosY;
fCaption:=aCaption;
fLoaded:=True;
end;
procedure TSettings.SaveSettings(aFilePath:string);
var
ConfigFile: TIniFile;
begin
try
try
ConfigFile:=TIniFile.Create(aFilePath);
except
on EInOutError do writeln('File can not be open!');
end;
ConfigFile.WriteString('Windows settings','width',IntToStr(Width));
ConfigFile.WriteString('Windows settings','height',IntToStr(Height));
ConfigFile.WriteString('Windows settings','posX',IntToStr(PosX));
ConfigFile.WriteString('Windows settings','posY',IntToStr(PosY));
ConfigFile.WriteString('Windows settings','caption',Caption);
finally
ConfigFile.Free;
end;
end;
procedure TSettings.SaveSettings();
begin
SaveSettings(fFilePath);
end;
procedure TSettings.SetWidth(aWidth:integer);
begin
if aWidth in [1..1920] then fWidth:=aWidth
else fWidth:=640;
end;
procedure TSettings.SetHeight(aHeight:integer);
begin
if aHeight in [1..1080] then fHeight:=aHeight
else fHeight:=480;
end;
procedure TSettings.SetPosX(aPosX:integer);
begin
if aPosX in [1..1920] then fPosX:=aPosX
else fPosX:=10;
end;
procedure TSettings.SetPosY(aPosY:integer);
begin
if aPosY in [1..1080] then fPosY:=aPosY
else fPosY:=10;
end;
procedure TSettings.SetCaption(aCaption: string);
begin
fCaption:=aCaption;
end;
procedure TSettings.SetFilePath(aFilePath:string);
begin
fFilePath:=aFilePath;
end;
end.
És amikor a főprogramodból hívod valami ilyesmi lesz:
Settings:=TSettings.Create(modname + '\scripts\settings.cfg');
InitOpenglwindow(Settings.Width, Settings.Height, Settings.PosX, Settings.PosY, Settings.Caption);
A kódot nem teszteltem le, így hibák lehetnek benne!
Még nem ástam bele magamat nagyon az ini fikeokba, mert nem.is akartam, de ezzel most kedvet csináltál nekem hozzá, látom te már ezt egy sokkal magasabb szinten ûzöd mint én, Mindig jó érzés ha a profiktól tanulhat az ember, és köszönöm, hogy segítettél még plusszban azon felûl amit kértem :). eltartott egy darabig, amíg megfelytettem ezt a kódot, de rájöttem, hogy sokkal hatékonyabb és gyorsabb is mint az enyém, csak egy dolog zaklat, úgy nézem itt elôre meg van adva, hogy mit is tudunk kinyerni a fileból (width, height, fov, stb.) ezzel csak az a problem, hogy ezek a filek jó hosszúak és lesz amit nem lehet elôre tudni belôle (pl. ez közben bele is került: intros=3
intro1=....
intro2=....
intro3=....
ez mondjuk egyszeruen egy tomb lenne de ez csak egy példa) meg lesznek olyan értékek, amiket mondjuk a felhasználó ad meg
( pl. fov ez bemegy string ként, majd visszajön a tárolt érték) azt nem tudom hogy oldjam meg így (mondjuk case of). De mindenesetre köszönöm, hogy rámszántad az idôdet, hogy segíts fejlôdni :)
:). Közel sem vagyok profi. A kód, amit az előző hozzászólásomban küldtem, több sebből vérzik. Csak hobbi szinten szoktam "bohóckodni" Lazarussal, Free Pascallal, szakmám szerint könyvtáros vagyok. Persze az igaz, hogy nem mostanában kezdtem foglalkozni a Pascal nyelv megismerésével.
Ha írsz egy programot, akkor olyan bemeneti adatod ne legyen, amit előre nem lehet tudni. Ha pedig lehet tudni, akkor már nem ismeretlen, így tehát lehet hozzá változót rendelni és így olyanra csinálhatod az osztályt, amilyenre kell.
Kapcsolódó kérdések:
Minden jog fenntartva © 2024, www.gyakorikerdesek.hu
GYIK | Szabályzat | Jogi nyilatkozat | Adatvédelem | Cookie beállítások | WebMinute Kft. | Facebook | Kapcsolat: info(kukac)gyakorikerdesek.hu
Ha kifogással szeretne élni valamely tartalommal kapcsolatban, kérjük jelezze e-mailes elérhetőségünkön!