Recent

Author Topic: [SOLVED] SetLength error  (Read 2825 times)

senglit

  • Full Member
  • ***
  • Posts: 131
[SOLVED] SetLength error
« on: October 23, 2020, 09:04:38 am »
Hi all,

I got a procedure in which SetLength is used. But everytime when it run to SetLength line, the program corrupted. I guess it is a very simple stupid problem. But I just can't figure it out. Who can remind me something about it?

Code: Pascal  [Select][+][-]
  1. type
  2.   PTrafficRecord = ^TrafficRecord;
  3.   TrafficRecord = record
  4.     Time:TDateTime;        
  5.     Interval:integer;      
  6.     Volume:integer;          
  7.     Index:integer;          
  8.   end;          
  9.  
  10. procedure TForm1.ReadHistoryTrafficData(const IndexFrom:integer;const IndexTo:integer);
  11. var
  12.   hd:array of TrafficRecord;
  13.   i,Len:integer;
  14. begin
  15.   if IndexFrom>IndexTo then exit;
  16.   Len:=IndexTo-IndexFrom+1;
  17.   SetLength(hd,Len);                                  //program corrupted here!!  
  18.   for i:=0 to IndexTo-IndexFrom do begin
  19.     //do something
  20.   end;            
  21.   SetLength(hd,0);
  22. end;                  
  23.  
« Last Edit: October 23, 2020, 04:00:13 pm by senglit »
I use Win10 + Lazarus 2.2.0 + FPC 3.2.2. All 64bit.

MarkMLl

  • Hero Member
  • *****
  • Posts: 6676
Re: SetLength error
« Reply #1 on: October 23, 2020, 09:28:35 am »
Corrupted /how/? What's your error message? How do you know that the length is >= 0?

MarkMLl
MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

senglit

  • Full Member
  • ***
  • Posts: 131
Re: SetLength error
« Reply #2 on: October 23, 2020, 10:16:34 am »
Corrupted /how/? What's your error message? How do you know that the length is >= 0?

MarkMLl

The Error looks like the attachment.

if IndexFrom>IndexTo then exit;
  Len:=IndexTo-IndexFrom+1;
  SetLength(hd,Len);

the length must be larger than 0
I use Win10 + Lazarus 2.2.0 + FPC 3.2.2. All 64bit.

senglit

  • Full Member
  • ***
  • Posts: 131
Re: SetLength error
« Reply #3 on: October 23, 2020, 10:52:51 am »
The strange thing is I used SetLenth many times in other procedures. But it only crash in this ReadHistoryTrafficData procedure.
I use Win10 + Lazarus 2.2.0 + FPC 3.2.2. All 64bit.

MarkMLl

  • Hero Member
  • *****
  • Posts: 6676
Re: SetLength error
« Reply #4 on: October 23, 2020, 10:58:15 am »
So look very carefully at the parameters being passed into that procedure. Apart from anything else they're signed... are you /sure/ that that check's effective in all possible cases?

MarkMLl
MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

senglit

  • Full Member
  • ***
  • Posts: 131
Re: SetLength error
« Reply #5 on: October 23, 2020, 11:12:33 am »
this line: if IndexFrom>IndexTo then exit;
should ensure the length is larger then 0

It also crashed if I change the line into : SetLength(hd,1000);

And I tried this:

var
cc:array of integer;
begin
 ...
 SetLength(cc,100);

end;

it crashed too! And SetLength only crash in this procedure. In others it works fine. What stupid thing I did?
I use Win10 + Lazarus 2.2.0 + FPC 3.2.2. All 64bit.

MarkMLl

  • Hero Member
  • *****
  • Posts: 6676
Re: SetLength error
« Reply #6 on: October 23, 2020, 11:35:21 am »
I know that check /should/ catch it, but I'm trying to give most of my attention to work at teh moment...

Are you sure that it's crashing where you think it's crashing? Does doing a line-by-line stepthrough show anything interesting? Does putting in WriteLn()s show anything interesting?

MarkMLl
MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

Paolo

  • Sr. Member
  • ****
  • Posts: 499
Re: SetLength error
« Reply #7 on: October 23, 2020, 12:20:06 pm »
What about if you move hd from procedure to global var ?
« Last Edit: October 23, 2020, 12:25:39 pm by Paolo »

rvk

  • Hero Member
  • *****
  • Posts: 6111
Re: SetLength error
« Reply #8 on: October 23, 2020, 12:44:23 pm »
Are you sure the error is on the SetLength() line?
(How did you check?)

Are you sure the instance of TForm1 is created?

How and where do you call ReadHistoryTrafficData?
« Last Edit: October 23, 2020, 12:51:45 pm by rvk »

howardpc

  • Hero Member
  • *****
  • Posts: 4144
Re: SetLength error
« Reply #9 on: October 23, 2020, 12:58:34 pm »
As always: code snippets are insufficient to debug programs from which they are just a small part.
Others can only guess at all the unknown other parts of your code.

Submitting a compilable example that reproduces the problem is the best way to elicit help from other programmers when you are stuck.

senglit

  • Full Member
  • ***
  • Posts: 131
Re: SetLength error
« Reply #10 on: October 23, 2020, 01:16:13 pm »
What about if you move hd from procedure to global var ?

I tried. But it happened again. Another strange thing is:

What I tried else includes:
Code: Pascal  [Select][+][-]
  1. procedure TForm1.ReadHistoryTrafficData(const IndexFrom:integer;const IndexTo:integer);
  2. var
  3.   cc:array of integer;
  4.   hd:array of TrafficRecord;
  5. begin
  6.   if IndexFrom>IndexTo then exit;
  7.   Len:=IndexTo-IndexFrom+1;
  8.   SetLength(cc,Len);      //check1
  9.   SetLength(hd,Len);     //check2
  10. end;
  11.  
  12. procedure TForm1.Button1Click(Sender: TObject);
  13. begin
  14.   ReadHistoryTrafficData(SpinEdit1.Value,SpinEdit2.Value);  //try 1
  15.   ReadHistoryTrafficData(10,20);  //try 2
  16. end;
  17.  

If I use "try1" line in Button1Click then both check1 and check2 will crush.
If I use "try2" line in Button1Click then check1 is ok and check2 will crush.
« Last Edit: October 23, 2020, 01:18:25 pm by senglit »
I use Win10 + Lazarus 2.2.0 + FPC 3.2.2. All 64bit.

senglit

  • Full Member
  • ***
  • Posts: 131
Re: SetLength error
« Reply #11 on: October 23, 2020, 01:23:55 pm »
Are you sure the error is on the SetLength() line?
(How did you check?)

Are you sure the instance of TForm1 is created?

How and where do you call ReadHistoryTrafficData?

I checked it by debugger Step to Step (F8). And I also check it by adding a lot of lines of MessageDlg() to ensure I know where I was.

The TForm1 Instance is created and The Form showed. It only crash when I click button1. and crashed in the first few lines when I tried to initialize the varaible in ReadHistoryTrafficData.

And the Form1 is the only Form in this program. and there is no thread is used. So I am very sure the problem is triggered by Button1.click.
« Last Edit: October 23, 2020, 01:32:12 pm by senglit »
I use Win10 + Lazarus 2.2.0 + FPC 3.2.2. All 64bit.

MarkMLl

  • Hero Member
  • *****
  • Posts: 6676
Re: SetLength error
« Reply #12 on: October 23, 2020, 01:24:45 pm »
If it really is crashing where you think it's crashing- and you've still not put in WriteLn()s to verify that- then it's time to try an older version of the compiler.

MarkMLl
MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

MarkMLl

  • Hero Member
  • *****
  • Posts: 6676
Re: SetLength error
« Reply #13 on: October 23, 2020, 01:28:31 pm »
And I also check it by adding a lot of lines of MessageDlg() to ensure I know where I was.

What use is that? You've got a crash in your program, something's behaving as though code generation is broken, and you expect the messageloop to be working properly? Oi vey!

Do you really think that most of us have never had to contend with this sort of thing? I said WriteLn() and I meant WriteLn()!!!!!

MarkMLl
MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

VisualLab

  • Sr. Member
  • ****
  • Posts: 290
Re: SetLength error
« Reply #14 on: October 23, 2020, 01:38:20 pm »
I have prepared a little test. Here is the code:

Code: Pascal  [Select][+][-]
  1. unit Unit1;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. interface
  6.  
  7. uses
  8.   Classes, SysUtils, Forms, Controls, Graphics, Dialogs, StdCtrls;
  9.  
  10. type
  11.   PTrafficRecord = ^TTrafficRecord;
  12.   TTrafficRecord = record
  13.     Time: TDateTime;
  14.     Interval: Integer;
  15.     Volume: Integer;
  16.     Index: Integer;
  17.   end;
  18.  
  19.   {TForm1}
  20.   TForm1 = class(TForm)
  21.     Button1: TButton;
  22.     Memo1: TMemo;
  23.     procedure Button1Click(Sender: TObject);
  24.   private
  25.     procedure ReadHistoryTrafficData(const AIndexFrom, AIndexTo: Integer);
  26.   public
  27.  
  28.   end;
  29.  
  30. var
  31.   Form1: TForm1;
  32.  
  33. implementation
  34.  
  35. {$R *.lfm}
  36.  
  37. {TForm1}
  38.  
  39. procedure TForm1.Button1Click(Sender: TObject);
  40. begin
  41.   ReadHistoryTrafficData(1, 10);
  42. end;
  43.  
  44. procedure TForm1.ReadHistoryTrafficData(const AIndexFrom, AIndexTo: Integer);
  45. var
  46.   VItem: PTrafficRecord;
  47.   VData: array of PTrafficRecord;
  48.   i, VCount, VSize: Integer;
  49.   VCurrentTime: TTime;
  50.   VText: String;
  51. begin
  52.   if AIndexFrom > AIndexTo
  53.    then Exit;
  54.   VCount := AIndexTo - AIndexFrom + 1;
  55.   SetLength(VData, VCount);
  56.   Memo1.Lines.Clear;
  57.   VCurrentTime := Now;
  58.   Randomize;
  59.   VSize := 0;
  60.   for i := 0 to AIndexTo - AIndexFrom do
  61.    begin
  62.     New(VItem);
  63.     VItem^.Index := i;
  64.     VItem^.Time := Now;
  65.     VItem^.Interval := Trunc(VCurrentTime - VItem^.Time);
  66.     VItem^.Volume := Random(1000);
  67.     VData[i] := VItem;
  68.     VSize := VSize + SizeOf(VItem^);
  69.     VText := 'i = ' + i.ToString +
  70.              ', time: ' + TimeToStr(VItem^.Time) +
  71.              ', interval: ' + VItem^.Interval.ToString +
  72.              ', volume: ' + VItem^.Volume.ToString;
  73.     Memo1.Lines.Add(VText);
  74.    end;
  75.   Memo1.Lines.Add('-----');
  76.   Memo1.Lines.Add('n: ' + VCount.ToString);
  77.   Memo1.Lines.Add('structure size: ' + VSize.ToString);
  78.   SetLength(VData, 0);
  79. end;
  80.  
  81. end.
  82.  

The code compiles. I also checked it with a debugger. I am not getting any error messages. I'm using: Windows 10, Lazarus 2.0.10.

VisualLab

 

TinyPortal © 2005-2018