简体   繁体   中英

TStringList.AddObject not working on Android (Delphi)

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)?

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));

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM