Watch, Follow, &
Connect with Us

For forums, blogs and more please visit our
Developer Tools Community.


Welcome, Guest
Guest Settings
Help

Thread: TList gives AV - does not work


This question is answered. Helpful answers available: 2. Correct answers available: 1.


Permlink Replies: 4 - Last Post: Jan 4, 2016 3:30 AM Last Post By: lawrence kartha...
lawrence kartha...

Posts: 16
Registered: 8/6/04
TList gives AV - does not work  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Dec 17, 2015 2:09 AM
Adding an object to a TList and then references them gives an access violation. This is pretty standard code that runs in delphi7 and DX in W64 mode but refuses to run on Android:

TData = class
FsData : string;
end;

procedure TForm1.ButtonRUNClick(Sender: TObject);
var
oList : TList;
oData : TData;
i : integer;
begin
oList := TList.Create;
for i := 0 to 20 do
begin
oData := TData.Create;
oData.FsData := IntToStr(oList.Count);
oList.Add(oData)
end;
Memo1.Lines.Clear;
Memo1.Lines.Add('Output');
try
for i := 0 to oList.Count - 1 do
begin
oData := TData(oList[i]);
Memo1.Lines.Add(oData.FsData)
end
except
on e: exception do
Memo1.Lines.Add(e.Message)
end;
oList.Free
end;

The memo reports access violation. XE7, XE8 and Seattle on Android various versions give this error.

Why?

Lawrence
Uwe Raabe

Posts: 180
Registered: 10/20/00
Re: TList gives AV - does not work  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Dec 17, 2015 2:55 AM   in response to: lawrence kartha... in response to: lawrence kartha...
lawrence karthauser wrote:

Adding an object to a TList and then references them gives an access
violation. This is pretty standard code that runs in delphi7 and DX
in W64 mode but refuses to run on Android:

TList is marked deprecated on ARC-Compilers (probably because of these
problems). Use TList<T>, TObjectList<T> or at least TObjectList instead.

In general: casting a Pointer to a TObject on ARC is a recipe for
desaster.

--
Uwe Raabe
Embarcadero MVP
lawrence kartha...

Posts: 16
Registered: 8/6/04
Re: TList gives AV - does not work  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Dec 18, 2015 2:18 AM   in response to: Uwe Raabe in response to: Uwe Raabe
Uwe Raabe wrote:
TList is marked deprecated on ARC-Compilers (probably because of these
problems). Use TList<T>, TObjectList<T> or at least TObjectList instead.

In general: casting a Pointer to a TObject on ARC is a recipe for
desaster.

I used TObjectList first and that is how I knew it did not work. I wanted to use the same syntax as D7.
It does work if I use a TStringlist as the base list and ignore the string bit - sorting off.

What is the correct way of using a pointer like that, I think the "AS" syntax is not available on Android?

If it is deprecated (why) should not the compiler throw a warning?

Lawrence
Remy Lebeau (Te...


Posts: 9,447
Registered: 12/23/01
Re: TList gives AV - does not work  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Dec 18, 2015 2:08 PM   in response to: lawrence kartha... in response to: lawrence kartha...
lawrence wrote:

I used TObjectList first and that is how I knew it did not work.

It should work. The non-Generic version of TObjectList is ARC-aware on mobile
systems, as has been since XE3. When an object is stored in the list, its
reference count gets incremented. When the object is removed from the list,
its reference count gets decremented. However, being derived from the non-Generic
TList, the non-Generic version of TObjectList still stores untyped pointers
internally. It is better to use the Generic versions of TList<T> and TObjectList<T>
on mobile systems to avoid that.

I wanted to use the same syntax as D7.

Then you need to use TObjectList instead of TList, especially if you want
the code to actually be compatible with D7:

uses
  ..., Contnrs;
 
procedure TForm1.ButtonRUNClick(Sender: TObject);
var
  oList : TObjectList;
  oData : TData;
  i : integer;
begin
  oList := TObjectList.Create(True);
  try
    for i := 0 to 20 do
    begin
      oData := TData.Create;
      oData.FsData := IntToStr(oList.Count);
      oList.Add(oData);
    end;
    Memo1.Lines.Clear;
    Memo1.Lines.Add('Output');
    try
      for i := 0 to oList.Count - 1 do
      begin
        oData := TData(oList[i]);
        Memo1.Lines.Add(oData.FsData);
      end;
    except
      on e: Exception do
        Memo1.Lines.Add(e.Message);
    end;
  finally
    oList.Free;
  end;
end;


Otherwise, use TObjectList<T> instead:

uses
  ..., System.Generics.Collections;
 
procedure TForm1.ButtonRUNClick(Sender: TObject);
var
  oList : TObjectList<TData>;
  oData : TData;
  i : integer;
begin
  oList := TObjectList<TData>.Create(True);
  try
    for i := 0 to 20 do
    begin
      oData := TData.Create;
      oData.FsData := IntToStr(oList.Count);
      oList.Add(oData);
    end;
    Memo1.Lines.Clear;
    Memo1.Lines.Add('Output');
    try
      for i := 0 to oList.Count - 1 do
      begin
        oData := oList[i];
        Memo1.Lines.Add(oData.FsData);
      end;
    except
      on e: Exception do
        Memo1.Lines.Add(e.Message);
    end;
  finally
    oList.Free;
  end;
end;

It does work if I use a TStringlist as the base list and ignore the string
bit - sorting off.

The TStrings.Objects[] property has always held TObject pointers, though
most people have abused that to hold non-TObject data, knowing that the RTL
would not actually touch the object data. But in mobile, where TObject is
ARC-enabled, means that the TStrings.Objects[] property now participates
in ARC reference counting, so you cannot store non-TObject data in TStrings.Objects[]
anymore.

The same applies to TList<T> when T is a class type, and TObjectList<T> (where
T is constrained to only class types).

What is the correct way of using a pointer like that

Stop using untyped pointers, and things that are based on untyped pointers.

I think the "AS" syntax is not available on Android?

Yes, it is. But you cannot use it on untyped pointers, and never could.

If it is deprecated (why) should not the compiler throw a warning?

Because the non-Generic TList and TObjectList classes are not actually marked
as 'deprecated' in the RTL source code on mobile platforms. They probably
should be.

--
Remy Lebeau (TeamB)
lawrence kartha...

Posts: 16
Registered: 8/6/04
Re: TList gives AV - does not work  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Jan 4, 2016 3:30 AM   in response to: lawrence kartha... in response to: lawrence kartha...
Thanks, it seems to work. But it didn't at first. It is strange that TStrings works as expected, but generic D7 TObjectlist doesn't.

I'll leave it with TStrings or TStringList for now as this works, but thanks

Lawrence

lawrence karthauser wrote:
Adding an object to a TList and then references them gives an access violation. This is pretty standard code that runs in delphi7 and DX in W64 mode but refuses to run on Android:

TData = class
FsData : string;
end;

procedure TForm1.ButtonRUNClick(Sender: TObject);
var
oList : TList;
oData : TData;
i : integer;
begin
oList := TList.Create;
for i := 0 to 20 do
begin
oData := TData.Create;
oData.FsData := IntToStr(oList.Count);
oList.Add(oData)
end;
Memo1.Lines.Clear;
Memo1.Lines.Add('Output');
try
for i := 0 to oList.Count - 1 do
begin
oData := TData(oList[i]);
Memo1.Lines.Add(oData.FsData)
end
except
on e: exception do
Memo1.Lines.Add(e.Message)
end;
oList.Free
end;

The memo reports access violation. XE7, XE8 and Seattle on Android various versions give this error.

Why?

Lawrence
Legend
Helpful Answer (5 pts)
Correct Answer (10 pts)

Server Response from: ETNAJIVE02