2

I am using RAD Studio XE-5 to create Android applications, but recently stumbled into a puzzling error. TStringList.AddObject raises the following exception:

Project Project3.apk raised exception class Segmentation fault (11).

My code is this

procedure TMainForm.FormCreate(Sender: TObject);
var
    list: TStrings;
begin
   list := TStringList.Create;
   list.AddObject('Joe', TObject(1)); // This is where exception is raised
   list.AddObject('Hans', TObject(2));
end;

This code runs perfectly fine on the 32-bit Windows target, but raises the aforementioned exception when run (in debug mode) on my Nexus 7 (which runs fine when I'm not using TStringList.AddObject). If I run the app without debug it just shuts down on my Nexus.

Is this a known problem/limitation of Delphi Android? Is there a workaround or a recommended way to achieve the same result (not just for this toy example but for using AddObject in general)?

4
  • 1
    The Android compiler uses ARC and therefor you cannot treat integers as objects as you did in Win32/64. Commented Oct 4, 2013 at 7:59
  • @StefanGlienke Does this mean that I could wrap an integer in a class (like Integer in java) and it should work? Commented Oct 4, 2013 at 8:04
  • 2
    Yes, see this blog article (it talks about iOS but the same applies to Android): blogs.riversoftavg.com/index.php/2013/08/01/… Commented Oct 4, 2013 at 8:04
  • Did you try casting to Pointer? Commented Oct 4, 2013 at 9:08

2 Answers 2

4

That whole style of programming was the way to do things back in the days of Delphi 7. But since those days, many things have changed. Most specifically the mobile compilers use ARC and they will attempt to destroy the objects held in the string list. That explains the error that you see.

The other change is the support for generics that was added in D2009. You should now use a type safe generic container for this task, rather than a string list. There are many around, but let's show an example with the built in class from Generics.Collections.

You need to create a list element type. It holds a string and an integer.

type
  TMyItem = record
  public
    Name: string;
    Age: Integer;
  end;

And let's make an easy way to make new ones:

function NewMyItem(const Name: string; const Age: Integer): TMyItem;
begin
  Result.Name := Name;
  Result.Age := Age;
end;

Then let's make a list of them:

var
  List: TList<TMyItem>;
....
List := TList<TMyItem>.Create;

And now add some items:

List.Add(NewMyItem('Joe', 1));
List.Add(NewMyItem('Hans', 2));
Sign up to request clarification or add additional context in comments.

4 Comments

Can I use this solution with a listbox? My original problem that spurred this question was that I was trying to save an Id on each item in a listbox, and ListBox.Items is of type TStrings.
The question states TStringList, and hence my answer. You cannot use this solution with a list box.
Does a ListBox in FMX support a virtual mode like it does in VCL? If so, then you can use a custom container and have the ListBox display it. Otherwise, just add strings to the ListBox and use its item indexes to access the container when needed.
@Daniel - a FMX TListBox is composed of a series of TListBoxItem sub-controls. As such, if you are adding items dynamically, you can create your own sub-class of TListBoxItem that has an extra Integer property (that's the best solution IMO). Alternatively, if the items are set up at design time, you could assign their Tag properties instead.
0

I do not know, why Stefan Glienke did not write their comment as an answer, but it is a really good another answer:

see this blog article (it talks about iOS but the same applies to Android): http://blogs.riversoftavg.com/index.php/2013/08/01/using-primitive-types-with-tstrings-in-ios/

Advice is to make a new wrapper class to wrap an Integer into a TObject, make for them class operator Implicit and Explicit to easy conversions and use a cast to this class instead of casts Integers to TObject and back to Integer. It minimizes required code changes.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.