Recent

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

MarkMLl

  • Hero Member
  • *****
  • Posts: 6676
Re: SetLength error
« Reply #15 on: October 23, 2020, 01:41:23 pm »
@VisualLab: same compiler version (3.2.0 64-bit)?

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 #16 on: October 23, 2020, 01:48:28 pm »
Yes.

Lazarus 2.0.10 r63526 FPC 3.2.0 x86_64-win64-win32/win64

Windows 10, Ent LTSC, 64-bit

VisualLab

rvk

  • Hero Member
  • *****
  • Posts: 6111
Re: SetLength error
« Reply #17 on: October 23, 2020, 01:51:55 pm »
What are your values for SpinEdit1.Value & SpinEdit2.Value?

Does  passing 1 and 1 work?

You error is definitely somewhere else and is probably memory related.
Did you create TForm1 yourself somewhere?

@VisualLab, if you just use setlength on array of TTrafficRecord in your example, does it crash for you?
(Because a small reproducable example with crash would be helpfull)
« Last Edit: October 23, 2020, 01:55:05 pm by rvk »

Cyrax

  • Hero Member
  • *****
  • Posts: 836
Re: SetLength error
« Reply #18 on: October 23, 2020, 01:57:19 pm »
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.  

Your program is 64-bit, right? Because address in the error message tells that your program is 32-bit one.

VisualLab

  • Sr. Member
  • ****
  • Posts: 290
Re: SetLength error
« Reply #19 on: October 23, 2020, 02:01:44 pm »
No. SetLength works fine in my code. I can preview what's going on in the code with a debugger. This is the result of the test application:

senglit

  • Full Member
  • ***
  • Posts: 131
Re: SetLength error
« Reply #20 on: October 23, 2020, 02:39:56 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

what a wonderful thing! I don't know why that happened to me. I use SetLength in many of my program. But it conly crash in this procedure.
I use Win10 + Lazarus 2.2.0 + FPC 3.2.2. All 64bit.

MarkMLl

  • Hero Member
  • *****
  • Posts: 6676
Re: SetLength error
« Reply #21 on: October 23, 2020, 02:48:39 pm »
Well if you do find out what's happening let us know. But I think you need to check an older compiler version.

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 #22 on: October 23, 2020, 03:56:43 pm »
@MarkMLl @VisualLab @rvk @Paolo @howardpc

Thanks for your warm hearted help! Finally I found the problem and here is the review of this stupid problem:

The program crashed at SetLength(hd,Len). @MarkMLl insist it is not the real problem. @VisualLab built a small sample to testify MarkMLl's opinion. But It always crashed at this step. I used F8 step debug, logfile and MessageDlg to confirm it really happened at this step.

But SetLength is a frequently used function and it never crashed before, even in this program. So I set breakpoints in all of the lines which used SetLength.

What was found: There is another procedure called by FormCreate. And there was something like

Code: Pascal  [Select][+][-]
  1. procedure ..........
  2. var
  3.   arr:array of word;
  4.   fs:TFileStream;
  5.   ......
  6. begin
  7.   SetLength(arr,Len1);
  8.   fs:=TFileStream.Create(filename,fmOpenRead or fmShareDenyNone);
  9.   fs.Position:=0;
  10.   fs.Read(arr[pos],len2);     //<---------------- stupid bug: pos+len2>len1. Modified, I wrote it wrongly at first time.
  11.   fs.Free;
  12. end;
  13.  


when this procedure is called by FormCreate, everything looks good. I can do anything on the Form1 window only if I don't click button1.

When button1 was clicked, this is the first time to run SetLength after the bug. Even hd is not arr the program still crashed.

So, another lesson for me: problem often happens before you can see it. Seek the real bug before the crash point.

Answer to Cyrax: I use win10 64bit and lazarus 64bit. But this program will run on a winxp 32bit system. So I installed a lazarus-cross-plateform and compile the program as a win32 exe file.

Thanks again to everybody!
« Last Edit: October 23, 2020, 04:04:38 pm by senglit »
I use Win10 + Lazarus 2.2.0 + FPC 3.2.2. All 64bit.

marcov

  • Administrator
  • Hero Member
  • *
  • Posts: 11383
  • FPC developer.
Re: SetLength error
« Reply #23 on: October 23, 2020, 03:59:56 pm »
You don't want to read into ARR, that is a  space for the 4/8 byte large pointer.

fs.read into arr[0]

senglit

  • Full Member
  • ***
  • Posts: 131
Re: SetLength error
« Reply #24 on: October 23, 2020, 04:06:04 pm »
You don't want to read into ARR, that is a  space for the 4/8 byte large pointer.

fs.read into arr[0]

Yes, you are right. I posted it wrongly. Modified. Thank you.
I use Win10 + Lazarus 2.2.0 + FPC 3.2.2. All 64bit.

MarkMLl

  • Hero Member
  • *****
  • Posts: 6676
Re: SetLength error
« Reply #25 on: October 23, 2020, 04:18:14 pm »
So, another lesson for me: problem often happens before you can see it. Seek the real bug before the crash point.

Old adage: when a programmer has a hard time finding a bug, it's because he's looking in the wrong place.

I wasn't necessarily saying it wasn't SetLength(), just that if you were 100% confident in your parameters and the runtime check then it wasn't happening where you were looking. And WriteLn() as I suggested- *NOT* a dialog(ue) box, should have shown that eventually.

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

 

TinyPortal © 2005-2018