Jump to content

Leaderboard


Popular Content

Showing content with the highest reputation on 08/05/22 in all areas

  1. That's up to the implementation of ReallocMem - the one that comes with Delphi (FastMM4) (I just looked into getmem.inc) has this comment:
  2. Those values in square brackets are custom attributes. Have a look at the documentation : https://docwiki.embarcadero.com/RADStudio/Alexandria/en/Declaring_Custom_Attributes_(RTTI)
  3. Vandrovnik

    [Android] How to change regional settings

    You can still use: var MyFormat: TFormatSettings; MyFormat:=TFormatSettings.Create; // obtains default settings if pos('yyyy', MyFormat.ShortDateFormat)<=0 then MyFormat.ShortDateFormat:=StringReplace(MyFormat.ShortDateFormat, 'yy', 'yyyy', []); ... DateToStr(now, MyFormat);
  4. Gustav Schubert

    Updating TPolygon items in generic List is difficult?

    Reading the bug report is one thing, understanding it another. I am dumping my test program here. It shows how to display the reference count of the dynamic array in the list. Comments in button click method will serve as alternative explanation for the same old problem you don't have. unit FrmMain; interface { 1. If you use new version of Delphi, please ignore. 2. In older version of Delphi, including Berlin, there is (known) bug. 3. Because of this bug (internal details already explained elsewhere) the reference count of the TPolygon will not be incremented when assigning to the list index. 4. When the assigned Polygon is a local variable which goes out of scope at the end of the method, it will be finalized and the list then contains a dangling pointer. 5. The AV only happens later, the next time the polygon is accessed. 6. The exception will likely be caught and handled by the debugger and following this the assignment will succeed. The newly assigned polygon will be usable, if the assigned polygon will not be finalized. 7. It is possible to monitor the reference count of the dynamic array. Stackoverflow question 22163259 has the answer that shows how. 8. The test program below has a timer which will update a report, which is showing the current ref count of the dynamic array in the list. - Usually the ref count of the polygon in the list is two. - After assigning a local variable with unique content it goes down to one. - The next time you click, the exception may happen, and ref count will be two again. - If assigning something that will not be finalized next, then the reference count can be left at one with no problem. - The biggest problem is the dangling pointer that is left behind, if any. - And the second biggest problem is the exception itself, which is not wanted. 9. Again, fixed in new version of Delphi! } uses Winapi.Windows, System.SysUtils, System.Classes, System.Types, System.StrUtils, System.UITypes, System.Math.Vectors, System.Generics.Collections, FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Controls.Presentation, FMX.StdCtrls, FMX.Objects; type { for Delphi 10.1. Berlin } TFormMain = class(TForm) Button1: TButton; Button2: TButton; Button3: TButton; Button4: TButton; Button5: TButton; Button6: TButton; Button7: TButton; T: TText; Timer: TTimer; procedure FormCreate(Sender: TObject); procedure FormDestroy(Sender: TObject); procedure TimerTimer(Sender: TObject); procedure Button1Click(Sender: TObject); procedure Button2Click(Sender: TObject); procedure Button3Click(Sender: TObject); procedure Button4Click(Sender: TObject); procedure Button5Click(Sender: TObject); procedure Button6Click(Sender: TObject); procedure Button7Click(Sender: TObject); private P1: TPolygon; P2: TPolygon; L: TList<TPolygon>; SL: TStringList; Counter: Integer; RefCountP1: Integer; RefCountP2: Integer; RefCountL0: Integer; procedure ShowContent; procedure SetupText; end; var FormMain: TFormMain; implementation {$R *.fmx} type { https://stackoverflow.com/questions/22163259/ } { how-i-determine-the-number-of-references-to-a-dynamic-array } PDynArrayRec = ^TDynArrayRec; TDynArrayRec = packed record {$IFDEF CPUX64} _Padding: LongInt; // Make 16 byte align for payload.. {$ENDIF} RefCnt: LongInt; Length: NativeInt; end; function DynArrayRefCount(P: Pointer): LongInt; begin if P <> nil then Result := PDynArrayRec(PByte(P) - SizeOf(TDynArrayRec))^.RefCnt else Result := 0; end; procedure TFormMain.FormCreate(Sender: TObject); begin P1 := [TPointF.Create(1, 1)]; P2 := [TPointF.Create(2, 2)]; L := TList<TPolygon>.Create; L.Add(P1); SL := TStringList.Create; SetupText; Timer.Interval := 500; Button7.Text := 'Reset'; end; procedure TFormMain.FormDestroy(Sender: TObject); begin L.Free; SL.Free; end; procedure TFormMain.TimerTimer(Sender: TObject); begin ShowContent; end; procedure TFormMain.SetupText; begin T.VertTextAlign := TTextAlign.Leading; T.Width := 200; T.Height := 500; T.Font.Size := 16; {$ifdef MACOS} T.Font.Family := 'CourierNewPSMT'; {$else} T.Font.Family := 'Courier New'; {$endif} T.Font.Style := T.Font.Style + [TFontStyle.fsBold]; T.Opacity := 1.0; T.Color := TAlphaColors.Cornflowerblue; T.HitTest := False; end; procedure TFormMain.ShowContent; var P: TPointF; s: string; begin if L.Count < 1 then begin T.Text := 'L is Empty'; Exit; end; RefCountP1 := DynArrayRefCount(Pointer(P1)); RefCountP2 := DynArrayRefCount(Pointer(P2)); RefCountL0 := DynArrayRefCount(Pointer(L[0])); Inc(Counter); SL.Clear; SL.Add(IntToStr(Counter)); SL.Add(Format('RecCountP1 = %d', [RefCountP1])); SL.Add(Format('RecCountP2 = %d', [RefCountP2])); SL.Add(Format('RecCountL0 = %d', [RefCountL0])); for P in L[0] do begin s := Format('(%.2f, %.2f)', [P.X, P.Y]); SL.Add(s); end; T.Text := SL.Text; end; procedure TFormMain.Button1Click(Sender: TObject); begin { problem will show at this point when L.Items[0] is invalid } // CurrentRefCount := DynArrayRefCount(Pointer(L[0])); // if CurrentRefCount > 1 then // begin L.Items[0] := P1; // end; end; procedure TFormMain.Button2Click(Sender: TObject); begin { this does not change anything } L[0] := L[0]; end; procedure TFormMain.Button3Click(Sender: TObject); var Temp: TPolygon; i: Integer; begin { this is ok, if L[0] contains valid polygon } Temp := P1; // P1 will not be finalized after method ends i := DynArrayRefCount(Pointer(Temp)); // Assert(i = 3); if not (i = 3) then Beep; L[0] := Temp; end; procedure TFormMain.Button4Click(Sender: TObject); begin { will leave a dangling pointer in L[0] } L[0] := L[0] + P1; end; procedure TFormMain.Button5Click(Sender: TObject); var Temp: TPolygon; begin { will leave a dangling pointer in L[0] } Temp := L[0] + P1; L[0] := Temp; end; procedure TFormMain.Button6Click(Sender: TObject); var Temp: TPolygon; begin { will leave dangling pointer in L[0] } { but no exception here when clicked again } { because it is not accessed } Temp := P1 + P2; L.Delete(0); L.Insert(0, Temp); end; procedure TFormMain.Button7Click(Sender: TObject); begin { Reset, ref count of L[0] will be two again. } L.Clear; L.Add(P1); end; (* https://stackoverflow.com/questions/45958714/ delphi-dynamic-array-reference-counting *) end.
  5. Remy Lebeau

    Ignore exception type from code

    No (plus, that would require changing and recompiling the code, in which case you may as well just take out the offending code to begin with). But, you can accomplish something similar using breakpoints instead. Put a breakpoint at the beginning of the function, go into its properties, and disable the 'Break' option, and enable the 'Ignore subsequent exceptions' option. Then, put another breakpoint at the end of the function, go into its properties, and disable the 'Break' option, and enable the 'Handle subsequent exceptions' option.
  6. Edit. Sorry it's late.
×