Under iOS, When I use my app intensively I always receive after few time a low memory warnings following by a crash of my app. So I did this simple test :
var MyTexture : Texture;
while true do begin
MyTexture := buildTexture(aStream);
MyTexture.free;
MyTexture := nil;
end;
Normally this must run undefinitively without any problems. However after one or 2 minutes i receive a low memory warnings and soon after my app is closed.
Why I have a memory Leak here ?
UPDATE / NOTE
I work all the day to isolate exactly where the problem is, and to gave a full working example. the problem wasn't in ttexture but in the use of UIIMAGE. so i reproduce below a working example (you just need to add to the project any jpg resource you want and named it 'test')
uses iOSapi.UIKit,
iOSapi.Foundation;
Procedure CreateAndFreeUIImage(const aStream: TCustomMemoryStream);
var aImage: UIimage;
aData: NSData;
begin
aData :=
TNSData.Wrap(TNSData.alloc.initWithBytesNoCopy(
aStream.Memory, // bytes: A buffer containing data for the new object.
// If flag is YES, bytes must point to a memory block
// allocated with malloc.
aStream.Size, // length: The number of bytes to hold from bytes.
// This value must not exceed the length of bytes.
False)); // flag: If YES, the returned object takes ownership of the
// bytes pointer and frees it on deallocation.
try
if aData.length > 0 then begin
aImage :=
TUIImage.Wrap(TUIImage.alloc.initWithData(aData));
// Return Value: An initialized UIImage object,
// or nil if the method could not initialize the image from the specified data.
if aImage <> nil then begin
try
// this to force the creation of the image
TpointF.Create(aImage.size.Width, aImage.size.Height);
finally
aImage.release;
aImage := nil;
end;
end
end;
finally
aData.release;
aData := nil;
end;
end;
procedure TForm1.Button1Click(Sender: TObject);
var aStream: TResourceStream;
begin
aStream := TResourceStream.Create(HInstance, 'test', RT_RCDATA);
button1.Tag := button1.Tag + 1;
button1.Text := 'running ('+inttostr(button1.Tag) + ' thread(s))';
TThread.CreateAnonymousThread(
procedure
begin
while true do begin
CreateAndFreeUIImage(aStream);
// sleep(100); // << if you uncomment this then it's work !
end;
end).Start;
end;
so when you click on the button, you will create and free (in infinite loop) an UIImage. very soon after you will receive in the log one low memory warnings following by the hard shutdown of the app.
just adding sleep(100) inside the loop and then app will never crash (at least i didn't see it crashing)
also to remove one hypothese, from https://developer.apple.com/reference/uikit/uiimage you can read that uiimage is multithread (so the error is not on this)
so it's seam that the memory is not clear immediately after we release the object, this resulting in the memory growing as we create more object than the memory release (it's what i understand).
is it a bug ? what is the workaround ? is their any way to force the release of the image (or to garbage of the memory?)
OK, i found the problem ! in ios, object are not free immediately but later on the next autorelease iteration (sound crazy for me).
so the workaround is very simple :
AutoReleasePool := TNSAutoreleasePool.Create;
try
... do you code
finally
AutoReleasePool.release; // << will free right now all the object
end;
now i don't know the speed penalty of using this ...