Jump to content
billyb

debug IOS using instruments Leak detector

Recommended Posts

Setup is delphi 10.4.2 - xcode 13  - sdk 15

I was finaly able to get instruments to work on my IOS app. (Had to build using developer cert and profile not adHoc)

Where I run my app, with Leaks this is what I see for a short timestamp. 

My question is are all these leaks?  How do I relate this to my code?

In several cases, the program is just sitting on a screen waiting for user input, but the leak list keep growing.

There are no timers in my program.

 

Leaked Object    Count    Address    Size    Responsible Library    Responsible Frame
Malloc 96 Bytes    1    0x285eeaca0    96 Bytes    CodeRouteTest    0x100f1221c
Malloc 96 Bytes    1    0x285f16460    96 Bytes    CodeRouteTest    0x100f1221c
Malloc 96 Bytes    1    0x285eeaee0    96 Bytes    CodeRouteTest    0x100f1221c
Malloc 96 Bytes    1    0x285eed5c0    96 Bytes    CodeRouteTest    0x100f1221c
Malloc 96 Bytes    3    < multiple >    288 Bytes    CodeRouteTest    0x100f1221c
Malloc 96 Bytes    1    0x285f164c0    96 Bytes    CodeRouteTest    0x100f1221c
Malloc 96 Bytes    1    0x285f67360    96 Bytes    CodeRouteTest    0x100f1221c
Malloc 80 Bytes    1    0x281d28500    80 Bytes    CodeRouteTest    0x100f1221c
Malloc 96 Bytes    1    0x285f161c0    96 Bytes    CodeRouteTest    0x100f1221c
Malloc 96 Bytes    2    < multiple >    192 Bytes    CodeRouteTest    0x100f1221c
IFMXTextPosition    1    0x2839d6290    16 Bytes    CodeRouteTest    0x10104de08
Malloc 96 Bytes    1    0x285f16b80    96 Bytes    CodeRouteTest    0x100f1221c
Malloc 96 Bytes    1    0x285ee8ea0    96 Bytes    CodeRouteTest    0x100f1221c
IFMXTextPosition    1    0x2839d5c90    16 Bytes    CodeRouteTest    0x10104de08
Malloc 96 Bytes    1    0x285f16580    96 Bytes    CodeRouteTest    0x100f1221c
Malloc 96 Bytes    1    0x285ee94a0    96 Bytes    CodeRouteTest    0x100f1221c
Malloc 96 Bytes    1    0x285eeba20    96 Bytes    CodeRouteTest    0x100f1221c
Malloc 96 Bytes    1    0x285eeb000    96 Bytes    CodeRouteTest    0x100f1221c
Malloc 96 Bytes    1    0x285eef420    96 Bytes    CodeRouteTest    0x100f1221c
IFMXTextRange    1    0x2839d5170    16 Bytes    CodeRouteTest    0x10104de08
Malloc 96 Bytes    1    0x285f66460    96 Bytes    CodeRouteTest    0x100f1221c
Malloc 96 Bytes    1    0x285eec420    96 Bytes    CodeRouteTest    0x100f1221c
Malloc 96 Bytes    2    < multiple >    192 Bytes    CodeRouteTest    0x100f1221c
Malloc 96 Bytes    1    0x285ee9020    96 Bytes    CodeRouteTest    0x100f1221c
Malloc 80 Bytes    1    0x281d284b0    80 Bytes    CodeRouteTest    0x100f1221c
Malloc 96 Bytes    1    0x285ee8a80    96 Bytes    CodeRouteTest    0x100f1221c
Malloc 96 Bytes    1    0x285eead00    96 Bytes    CodeRouteTest    0x100f1221c
Malloc 96 Bytes    1    0x285ee2340    96 Bytes    CodeRouteTest    0x100f1221c
Malloc 96 Bytes    1    0x285eed680    96 Bytes    CodeRouteTest    0x100f1221c
Malloc 96 Bytes    1    0x285eead60    96 Bytes    CodeRouteTest    0x100f1221c
Malloc 96 Bytes    1    0x285f163a0    96 Bytes    CodeRouteTest    0x100f1221c
Malloc 96 Bytes    1    0x285f16ac0    96 Bytes    CodeRouteTest    0x100f1221c
UICTFontDescriptor    1    0x285f17ae0    96 Bytes    UIFoundation    -[UIFontDescriptor _swapWithFontAttributes:options:]
UICTFontDescriptor    1    0x285ee5200    96 Bytes    UIFoundation    -[UIFontDescriptor _swapWithFontAttributes:options:]
Malloc 80 Bytes    1    0x281d280f0    80 Bytes    CodeRouteTest    0x100f1221c
 

Share this post


Link to post
6 hours ago, billyb said:

IFMXTextPosition

This one possibly means there's a bug in TFMXTextRange.Destroy (FMX.Platform.iOS on line 1768 in 10.4.2). The references are being set to nil, but they're Delphi object references. Some of the others may be happening as a result. One way to check would be to make a copy of FMX.Platform.iOS and put it in the project folder, then modify TFMXTextRange.Destroy to call Free on the references

Share this post


Link to post

Dave,

 

I modified FMX.Platform.iOS, added it to my uses but it does not appear to make any difference in the leaks.

 

program CodeRouteTest;

uses
  System.StartUpCopy,
  {$IF Defined(IOS) and Defined(CPUARM)}
  IdSSLOpenSSLHeaders_Static,
  {$ELSE}
  IdSSLOpenSSLHeaders,
  {$ENDIF }
  {$IF Defined(IOS)}
     uMachExt in '..\..\..\BASE\MOBILE\Common\uMachExt.pas',
  {$ENDIF}
  FMX.PLATFORM.IOS IN 'FMX.PLATFORM.IOS.PAS',
  FMX.Forms,
 

 

destructor TFMXTextRange.Destroy;
begin
  FStart.free; // added by bb
  FEnd.free;  // added by bb

  FStart := nil;
  FEnd := nil;
  inherited;
end;
 

I still get the TextRange errors as well as othe FMX errors

Leaked Object    Count    Address    Size    Responsible Library    Responsible Frame
IFMXTextPosition    1    0x282c1fb70    16 Bytes    CodeRouteTest    0x100829e08
UICTFontDescriptor    1    0x280a69200    96 Bytes    UIFoundation    -[UIFontDescriptor _swapWithFontAttributes:options:]
UICTFontDescriptor    1    0x280b07a20    96 Bytes    UIFoundation    -[UIFontDescriptor _swapWithFontAttributes:options:]
Malloc 96 Bytes    1    0x280a5d860    96 Bytes    CodeRouteTest    0x1006ee21c
UICTFontDescriptor    5    < multiple >    480 Bytes    UIFoundation    -[UIFontDescriptor _swapWithFontAttributes:options:]
UICTFontDescriptor    1    0x2804671e0    96 Bytes    UIFoundation    -[UIFontDescriptor _swapWithFontAttributes:options:]
Malloc 96 Bytes    4    < multiple >    384 Bytes    CodeRouteTest    0x1006ee21c
Malloc 96 Bytes    1    0x280b27780    96 Bytes    CodeRouteTest    0x1006ee21c
Malloc 96 Bytes    3    < multiple >    288 Bytes    CodeRouteTest    0x1006ee21c
Malloc 96 Bytes    1    0x280a4a520    96 Bytes    CodeRouteTest    0x1006ee21c
Malloc 96 Bytes    1    0x280b17420    96 Bytes    CodeRouteTest    0x1006ee21c
UICTFontDescriptor    1    0x280a41800    96 Bytes    UIFoundation    -[UIFontDescriptor _swapWithFontAttributes:options:]
Malloc 96 Bytes    1    0x280b272a0    96 Bytes    CodeRouteTest    0x1006ee21c
UICTFontDescriptor    1    0x280b1e8e0    96 Bytes    UIFoundation    -[UIFontDescriptor _swapWithFontAttributes:options:]
Malloc 96 Bytes    4    < multiple >    384 Bytes    CodeRouteTest    0x1006ee21c
Malloc 80 Bytes    1    0x280dabca0    80 Bytes    CodeRouteTest    0x1006ee21c
UICTFontDescriptor    2    < multiple >    192 Bytes    UIFoundation    -[UIFontDescriptor _swapWithFontAttributes:options:]
Malloc 96 Bytes    3    < multiple >    288 Bytes    CodeRouteTest    0x1006ee21c
Malloc 96 Bytes    1    0x280ae0fc0    96 Bytes    CodeRouteTest    0x1006ee21c
Malloc 80 Bytes    3    < multiple >    240 Bytes    CodeRouteTest    0x1006ee21c
Malloc 80 Bytes    3    < multiple >    240 Bytes    CodeRouteTest    0x1006ee21c
Malloc 96 Bytes    1    0x280b535a0    96 Bytes    CodeRouteTest    0x1006ee21c
UICTFontDescriptor    1    0x28042a160    96 Bytes    UIFoundation    -[UIFontDescriptor _swapWithFontAttributes:options:]
Malloc 96 Bytes    3    < multiple >    288 Bytes    CodeRouteTest    0x1006ee21c
UICTFontDescriptor    1    0x280ab8840    96 Bytes    UIFoundation    -[UIFontDescriptor _swapWithFontAttributes:options:]
IFMXTextRange    3    < multiple >    48 Bytes    CodeRouteTest    0x100829e08
UICTFontDescriptor    1    0x284a6e4c0    96 Bytes    UIFoundation    -[UIFontDescriptor _swapWithFontAttributes:options:]
Malloc 96 Bytes    4    < multiple >    384 Bytes    CodeRouteTest    0x1006ee21c
UICTFontDescriptor    1    0x280476f40    96 Bytes    UIFoundation    -[UIFontDescriptor _swapWithFontAttributes:options:]
UICTFontDescriptor    5    < multiple >    480 Bytes    UIFoundation    -[UIFontDescriptor _swapWithFontAttributes:options:]
UICTFontDescriptor    1    0x280440ae0    96 Bytes    UIFoundation    -[UIFontDescriptor _swapWithFontAttributes:options:]
UICTFontDescriptor    1    0x2804293e0    96 Bytes    UIFoundation    -[UIFontDescriptor _swapWithFontAttributes:options:]
UICTFontDescriptor    1    0x28045cea0    96 Bytes    UIFoundation    -[UIFontDescriptor _swapWithFontAttributes:options:]
Malloc 96 Bytes    1    0x280b52ca0    96 Bytes    CodeRouteTest    0x1006ee21c
Malloc 96 Bytes    5    < multiple >    480 Bytes    CodeRouteTest    0x1006ee21c
IFMXTextRange    1    0x282c1a140    16 Bytes    CodeRouteTest    0x100829e08
Malloc 96 Bytes    3    < multiple >    288 Bytes    CodeRouteTest    0x1006ee21c
UICTFontDescriptor    3    < multiple >    288 Bytes    UIFoundation    -[UIFontDescriptor _swapWithFontAttributes:options:]
Malloc 96 Bytes    1    0x280aad4a0    96 Bytes    CodeRouteTest    0x1006ee21c
IFMXTextPosition    1    0x282c1a230    16 Bytes    CodeRouteTest    0x100829e08
UICTFontDescriptor    1    0x28041a9a0    96 Bytes    UIFoundation    -[UIFontDescriptor _swapWithFontAttributes:options:]
IFMXTextPosition    1    0x282c05140    16 Bytes    CodeRouteTest    0x100829e08
Malloc 96 Bytes    3    < multiple >    288 Bytes    CodeRouteTest    0x1006ee21c
 

 

 

Share this post


Link to post
4 hours ago, billyb said:

it does not appear to make any difference in the leaks.

I guess I was wrong about that part 🙂

Share this post


Link to post

Dave,

 

Your change made sense, I tried to look for other objects in a .destroy method that did not have a object.free.

did not find any in fmx.platform.ios.pas that should be free'd

 

I hate IOS. 

Share this post


Link to post
1 hour ago, Dave Nottage said:

I guess I was wrong about that part 🙂

Maybe not.... I haven't looked at iOS since Rio was released and I haven't used it with 10.4 when ARC compiler was removed. 

 

There are some weird changes in Macapi.ObjectiveC specifically in TOCLocal class declaration which now uses TOCInterfacedObject. But that requires deeper look and I cannot do that right now, plus I don't have my Mac fully setup to work with Delphi. But, maybe it will give you some clues as where to look.

 

It seems like changes are there to prevent reference counting destroying the object, but in that case there is definitely need for calling Free on anything constructed. Unless compiler is doing some magic behind the scenes for those classes.

Share this post


Link to post

Dalija,

 

I have really no understanding of IOS Objective C so I am not in a postion to review the code. Any suggestions on Code changes in "Macapi.ObjectiveC" I am happy to try. 

 

Is this the code you are referring to?  I see FObjectID created, but not free'd in the destroy event. 

Also the {$IFDEF AUTOREFCOUNT} is never used as both defined and not defined statments to release are commented out.

 

constructor TOCLocal.Create;
var
  CType: PTypeInfo;
  Reg: TRegisteredDelphiClass;
begin
  inherited;

  CType := PTypeInfo(Self.ClassType.ClassInfo);
  Reg := TRegisteredDelphiClass.RegisterClass(CType, GetObjectiveCClass);
  FObjectID := Reg.CreateObj(Self);
{$IFDEF DEBUGUTILS}
  TDebugUtils.DebugPrint('oc.local.create', 'Created instance of ''%s'' ObjID = 0x%x',
             [Self.ClassName, IntPtr(FObjectID)]);
{$ENDIF}
  if FObjectID = nil then
    raise EObjectiveC.CreateResFmt(@SErrorCreatingOCObject, [CType^.NameFld.ToString]);
end;

 

destructor TOCLocal.Destroy;
begin
{$IFDEF DEBUGUTILS}
  TDebugUtils.DebugPrint('oc.local.destroy', 'Destroying instance of ''%s'' ObjID = 0x%x',
    [Self.ClassName, IntPtr(FObjectID)]);
{$ENDIF}
{$IFDEF AUTOREFCOUNT}
//  objc_msgSend(FObjectID, sel_registerName('release'));
{$ELSE AUTOREFCOUNT}
//  objc_msgSend(FObjectID, sel_registerName('autorelease'));
{$ENDIF AUTOREFCOUNT}
  inherited Destroy;
end;
 

 

Share this post


Link to post
1 hour ago, Dalija Prasnikar said:

which now uses TOCInterfacedObject

I hadn't noticed that, thanks!

Share this post


Link to post
10 hours ago, billyb said:

I have really no understanding of IOS Objective C so I am not in a postion to review the code. Any suggestions on Code changes in "Macapi.ObjectiveC" I am happy to try. 

 

Is this the code you are referring to?  I see FObjectID created, but not free'd in the destroy event. 

Also the {$IFDEF AUTOREFCOUNT} is never used as both defined and not defined statments to release are commented out.

There is no "unified" handling of the TOCLocal instances, because what you need to do depends on how you got the instance. So that part seems fine.

 

destructor TFMXTextRange.Destroy;
begin
  FStart.free; // added by bb
  FEnd.free;  // added by bb

  inherited;
end;

 

As far as TFMXTextRange is concerned there should definitely be calls to Free, niling is redundant. But, those classes are reference counted, so they should have never been stored in object references to begin with FStart: TFMXTextPosition is wrong (and if they would be stored in interface references then Free would not be needed). This is where those changes in TOCInterfacedObject possibly come to play, to prevent issues with reference counting and allowing instances to be stored in object references. But in that case anything stored in interface reference would be broken. 

 

So the whole thing is a bit incomprehensible to me right now, because it also depends on how is each instance stored (interface or object reference), whether Free is called or not. The only way to easily see what is going on is through debugging and I cannot do that right now.

 

Bottom line... FStart.Free and FEnd.Free should have some impact on reducing number of leaks, but it is quite possible that there are other leaks due to changes in TOCLocal.

 

If you put breakpoint at FStart := nil you should be able to see whether TFMXTextPosition.Destroy is called. If it is then, niling is fine. If not, try with FStart.Free. If that calls destructor that is first fix you need to do. If you still have leaks, you can try calling FStart.Release before FStart.Free to explicitly release ObjectiveC object behind it. If you get segmentation fault afterwards, then this is wrong. 

 

I am sorry that I cannot be of more help.

Share this post


Link to post

Dalija,

 

Thank you for the support. I tried to put a breakpoint on the Fend := nil; but it will not let me (shows x) I can put breakpoints on other code in my program.

Not sure if this means anything...

Module Load: CodeRouteTest. Has Debug Info. Base Address: $00000001043D8000. Process CodeRouteTest (1004)
Module Load: dyld. No Debug Info. Base Address: $000000010A9AC000. Process CodeRouteTest (1004)

 

I did try adding fend._release before fend.free and it crashes 

Exception Type:  EXC_CRASH (SIGABRT)
 

This is way outside my knowledge area. 

 

My program has lots of input text fields accross multiple form. Program runs for hrs before memory errors.

 

Not sure where to go from here.  But I will continue to review what you said and see if I can get a better understanding.

 

Again thank you for you help.

 

Bill B

Share this post


Link to post

OK, I built a single form test app (MEMLEAK)  with 3 edit's and 1 memo on the form

I set the memo control type to PLATFORM so that voice typing works.

Here is leaks..

 

Leaked Object    Count    Address    Size    Responsible Library    Responsible Frame
IFMXTextRange    1    0x28072e770    16 Bytes    memleak    0x1050701a4
IFMXTextPosition    1    0x28072e780    16 Bytes    memleak    0x1050701a4
Malloc 48 Bytes    1    0x280b5db30    48 Bytes    memleak    0x1051eb56c
Malloc 80 Bytes    1    0x28267a0d0    80 Bytes    memleak    0x104f3bd68
NSMutableDictionary    1    0x280543c00    32 Bytes    memleak    0x1051eb56c
UICTFontDescriptor    1    0x282178180    96 Bytes    UIFoundation    -[UIFontDescriptor _swapWithFontAttributes:options:]
Malloc 80 Bytes    1    0x28267a210    80 Bytes    memleak    0x104f3bd68
UICTFontDescriptor    1    0x28217c540    96 Bytes    UIFoundation    -[UIFontDescriptor _swapWithFontAttributes:options:]
UICTFontDescriptor    1    0x282178420    96 Bytes    memleak    0x1051eb56c
IFMXTextPosition    1    0x28072e3f0    16 Bytes    memleak    0x1050701a4
UICTFontDescriptor    1    0x2821784e0    96 Bytes    UIFoundation    -[UIFontDescriptor _swapWithFontAttributes:options:]
Malloc 80 Bytes    1    0x28267a030    80 Bytes    memleak    0x104f3bd68
IFMXTextPosition    1    0x28072c990    16 Bytes    memleak    0x1050701a4
IFMXTextRange    1    0x28072e3d0    16 Bytes    memleak    0x1050701a4
__NSFontExtraData    1    0x281003a00    64 Bytes    UIFoundation    __CTFontGetExtraData
UICTFontDescriptor    1    0x2821633c0    96 Bytes    UIFoundation    -[UIFontDescriptor _swapWithFontAttributes:options:]
UICTFontDescriptor    1    0x2821781e0    96 Bytes    UIFoundation    -[UIFontDescriptor _swapWithFontAttributes:options:]
UICTFontDescriptor    1    0x282117540    96 Bytes    UIFoundation    -[UIFontDescriptor _swapWithFontAttributes:options:]
UICTFontDescriptor    1    0x28216a2e0    96 Bytes    UIFoundation    -[UIFontDescriptor _swapWithFontAttributes:options:]
UICTFontDescriptor    1    0x2821668e0    96 Bytes    UIFoundation    -[UIFontDescriptor _swapWithFontAttributes:options:]
Malloc 80 Bytes    1    0x28267a260    80 Bytes    memleak    0x104f3bd68
UICTFont    1    0x10872ad70    544 Bytes    memleak    0x1051eb56c
UICTFontDescriptor    1    0x282169020    96 Bytes    UIFoundation    -[UIFontDescriptor _swapWithFontAttributes:options:]
IFMXTextPosition    1    0x28072e6d0    16 Bytes    memleak    0x1050701a4
IFMXTextPosition    1    0x28072e6f0    16 Bytes    memleak    0x1050701a4
IFMXTextPosition    1    0x28072e600    16 Bytes    memleak    0x1050701a4
 

 

I then ran again with memo control style set to STYLED.

 

Leaked Object    Count    Address    Size    Responsible Library    Responsible Frame
UICTFontDescriptor    1    0x2814042a0    96 Bytes    UIFoundation    -[UIFontDescriptor _swapWithFontAttributes:options:]
UICTFontDescriptor    1    0x2814062e0    96 Bytes    UIFoundation    -[UIFontDescriptor _swapWithFontAttributes:options:]
UICTFontDescriptor    1    0x28140dfe0    96 Bytes    UIFoundation    -[UIFontDescriptor _swapWithFontAttributes:options:]
UICTFontDescriptor    1    0x28140ca20    96 Bytes    UIFoundation    -[UIFontDescriptor _swapWithFontAttributes:options:]
 

In both cases UICTFontDescriptor is showing as leading in UIFoundation 

But using Platform as control type on memo results in a lot of reported leaks.

 

Any thoughts on this?  

Share this post


Link to post

Added tab control to my test app and the leaks are much worse on entering text into any edit control on tab pages.

 

Create QC report RSP-35955

 

I find it hard to believe that my test app has so many leaks 

Can anyone verify what I am seeing?

 

Thank you

 

Bill B

 

 

Edited by billyb
add more details

Share this post


Link to post

Finaly got a response on this issue from embarcadero,

 

Created By: David Powell (11/11/2021 2:11 AM) | Last Modified By: David Powell (11/11/2021 2:11 AM)
After speaking with development they are aware of a couple of reported memory leaks related to edit and memo controls on iOS/iPadOS. They are all related to IFMXTextRange and IFMXTextPosition. This has not been fixed in version 11. I had asked previously in anticipation that development would want that information.

At this point there is no workaround to the issue. Development will have to address the problem in a future update or release. Make certain that you are a Watcher on both RSP-35955 and RSP-35620 so that you will be automatically notified if the status changes or if development posts additional information.

Best Regards,

- David Powell
Support Manager - Developer Tools

  • Thanks 1

Share this post


Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×