Lazarus
Programming => LCL => Topic started by: Ruptor on February 07, 2013, 01:49:39 am
-
It appears that if a stringlist that has not been loaded is freed the system gives an exception error SIGSEGV. I read about debugger problems but it happens using the exe file. Is this a compiler problem or is to be expected and down to the user not to do it?
I am using windows XP, fpc 2.6.1, Lazarus 1.1 r40186
-
show us some code to better understand your position "string list that has not been loaded" has at least 2 different interpretations
1) the object has been created but no data has been inserted in it.
2) The object has not been created.
in the 1st case freeing the object should work in the second it should not.
-
Here is what is left of the procedure after I chopped everything out of it to find the problem.
procedure TForm1.Button2Click(Sender: TObject);
var
Str: TStringList;
Price: string;
PriceStr: Packed Array[1..300] of char;
cafl: array[0..1000] of Integer;
ask,bid,freq,y: Real;
code,ifreq,x: Integer;
asc,i,j,timsec: LongInt;
morech,opened:boolean;
begin
i:=0;
while i<1000 do
begin
cafl[i]:=0;
i:=i+1;
end;
Str.Free;
end;
Commenting out the STR.Free statement stops the exception.
-
Commenting out the STR.Free statement stops the exception.
Of course. You can not Free a non-created object.
-
Why doesn't the compiler say something? It warns about uninitialised variables so why not objects?
-
I just copied your code. And I get all of the below messages.
Starts with a warning about Str.
unit1.pas(48,3) Warning: Local variable "Str" does not seem to be initialized
unit1.pas(34,3) Note: Local variable "Price" not used
unit1.pas(35,3) Note: Local variable "PriceStr" not used
unit1.pas(36,3) Note: Local variable "cafl" is assigned but never used
unit1.pas(37,3) Note: Local variable "ask" not used
unit1.pas(37,7) Note: Local variable "bid" not used
unit1.pas(37,11) Note: Local variable "freq" not used
unit1.pas(37,16) Note: Local variable "y" not used
unit1.pas(38,3) Note: Local variable "code" not used
unit1.pas(38,8) Note: Local variable "ifreq" not used
unit1.pas(38,14) Note: Local variable "x" not used
unit1.pas(39,3) Note: Local variable "asc" not used
unit1.pas(39,9) Note: Local variable "j" not used
unit1.pas(39,11) Note: Local variable "timsec" not used
unit1.pas(40,3) Note: Local variable "morech" not used
unit1.pas(40,10) Note: Local variable "opened" not used
-
Yes you are right I missed the new message but with the whole procedure in place the message doesn't occur. Here is the whole routine that I am messing around with.
procedure TForm1.Button2Click(Sender: TObject);
var
Str: TStringList;
Price: string;
PriceStr: Packed Array[1..300] of char;
cafl: array[0..1000] of Integer;
ask,bid,freq,y: Real;
code,ifreq,x: Integer;
asc,i,j,timsec: LongInt;
morech,opened:boolean;
begin
i:=0;
// while i<sizeof(cafl) do
while i<1000 do
begin
cafl[i]:=0;
i:=i+1;
end;
opened:=true;
Str := TStringList.Create;
try
Str.LoadFromFile(FileListBox1.FileName);
// Str.LoadFromFile(UTF8ToSys(FileListBox1.FileName));
except
opened:=false;
Edit2.text:='Cannot open file';
end;
if opened then
begin
if FileListBox1.Items.Count-1<>-1 then
begin
ProgressBar1.Min:=0;
ProgressBar1.Max:=Str.Count;
ProgressBar1.Step:=1;
ProgressBar1.StepBy(1);
Edit2.text:=inttostr(Str.Count);
BidLine.clear;
i:=0;
while i<Str.Count do
begin
PriceStr:=Str[i];
morech:=true;
Price:='';
j:=1;
while morech do
begin
asc:=ord(PriceStr[j]);
if (asc >=$30) and (asc <=$39) or (asc =$2E) then
begin
Price:=Price+PriceStr[j];
j:=j+1;
end
else
begin
if asc =$2C then
begin
val(Price,freq,code);
ifreq:=round(freq);
cafl[ifreq]:=cafl[ifreq]+1;
Price:='';
j:=j+1;
end
else morech:=false;
end;
end;
end;
ProgressBar1.StepIt;
i:=i+1;
end;
ifreq:=0;
while ifreq<sizeof(cafl) do
begin
x:=ifreq;
y:=cafl[ifreq];
BidLine.ADDXY(x,y);
ifreq:=ifreq+1;
end;
Edit2.text:=inttostr(ifreq);
end else
begin
Edit2.text:='File Empty';
end;
Str.Free;
end;
I suppose the compiler doesn't know that the stringlist might not be initialised but it should be since it is done after the first loop.
-
Well because in that code you do initialize it:
Str := TStringList.Create;
That is correct. The error must be in something else.
1) check the debugger is correctly setup (or rather your project):
http://wiki.lazarus.freepascal.org/Debugger_Setup
- No optimization, except level 1
- no smart linking
If you do have optimization level 2 or 3 it may show you the wrong line, or other wrong info.
2) Ensure you have "Range Check enabled.
I see no checks, that
cafl[ifreq]:=cafl[ifreq]+1;
ifreq stays within the 0..1000 of cafl.
If you write to an array member outside this range (and have no range check enabled, then you destroy other data. That is like a time bomb. So it is possible, this can cause the later crash.
-
I don't know if you meant it, but sizeof(cafl), when cafl is
cafl: array[0..1000] of Integer;
will result in 1001*4 = 4004. So last loops ifreq draws from 0 to 4003.
Firstly, if you intend data to go from 0..999, then array is defined 0..999. Last number in array definition means the Max value, not Count. Secondly, you can use High() to get index of last element (999), and Length() to get index count (1000). Then there's also Low() which tells the first index (0).
-
Well I ran my unchanged code this morning and the exception has gone. The code doesn't work of course but at least now I can test it. Thanks for finding the sizeof() problem before it occurred that has saved me a lot of time. It looks like once the error happened it was locked and resetting the debugger or even starting lazarus was not enough to clear it. A computer power off was required maybe because firefox was running all the time, I don't know. It smacks of a pointer problem in my code but strange that it hasn't happened after turning off the computer. It must still be there but maybe the way I have started the apps today the memory being screwed up is not being used.