billyb 1 Posted October 18, 2021 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
Dave Nottage 557 Posted October 19, 2021 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
billyb 1 Posted October 19, 2021 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
Dave Nottage 557 Posted October 19, 2021 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
billyb 1 Posted October 19, 2021 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
Dalija Prasnikar 1396 Posted October 19, 2021 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
billyb 1 Posted October 19, 2021 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
Dave Nottage 557 Posted October 19, 2021 1 hour ago, Dalija Prasnikar said: which now uses TOCInterfacedObject I hadn't noticed that, thanks! Share this post Link to post
Dalija Prasnikar 1396 Posted October 20, 2021 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
billyb 1 Posted October 20, 2021 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
billyb 1 Posted October 21, 2021 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
billyb 1 Posted October 23, 2021 (edited) 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 October 23, 2021 by billyb add more details Share this post Link to post
billyb 1 Posted November 15, 2021 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 1 Share this post Link to post