2016-12-19 3 views
1

Под iOS, когда я использую свое приложение интенсивно Я всегда получаю через несколько минут предупреждения о низкой памяти, следующие краху моего приложения. Поэтому я сделал это простое испытание:IOS + delphi: предупреждения о низкой памяти - возможная утечка памяти с TTexture?

var MyTexture : Texture; 

while true do begin 
    MyTexture := buildTexture(aStream); 
    MyTexture.free; 
    MyTexture := nil; 
end; 

Обычно это должно выполняться без каких-либо проблем. Однако через одну или две минуты я получаю предупреждения с низкой памятью и вскоре после закрытия моего приложения.

Почему у меня есть память Утечка здесь?

UPDATE/NOTE

Я работаю весь день, чтобы изолировать именно там, где проблема, и дал полный рабочий пример. проблема была не в ttexture, а в использовании UIIMAGE. поэтому я воспроизвести ниже рабочего примера (вам просто нужно добавить в проект любой JPG ресурс, который вы хотите, и назвал его «тест»)

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; 

поэтому при нажатии на кнопку, вы будете создавать и бесплатно (в бесконечный цикл) UIImage. очень скоро после того, как вы получите в журнале один предупреждения о низкой памяти, следующие за жестким отключением приложения.

просто добавить сон (100) внутри цикла, а затем приложение никогда не сломается (по крайней мере, я не видел его врезаться)

также удалить один hypothese из https://developer.apple.com/reference/uikit/uiimage вы можете прочитать, что UIImage является многопоточной (так что ошибка не в этом)

так это шов, что память не ясно, сразу после того, как мы освобождаем объект, это приводит к памяти растет, как мы создаем больше объектов, чем выпуск памяти (это то, что я понимаю,).

Это ошибка? каково обходное решение? это их способ принудительно освободить изображение (или от мусора памяти?)

+2

Возможно, утечка в 'buildTexture', которые мы не можем видеть. Разве у нас нет [mcve]. И зачем использовать 'Free' и задавать переменную' nil', а затем перезаписывать переменную. Вам нужно только сделать это. Поскольку вы хотите перезаписать, вы можете удалить последние две строки цикла. –

+0

@DavidHeffernan не будет удалять ** 2 ** последние строки кода меняют способ, которым он должен себя вести? Предположительно пример OP демонстрирует mem-leak в создании/уничтожении TTexture. Разумеется, создание множества объектов без уничтожения может привести к утечке памяти. – Kromster

+0

@Kromster No. Это мобильный компилятор с ARC. –

ответ

1

ОК, я нашел проблему! в ios, объект не является бесплатным сразу, а позже на следующей итерации авторешетки (звук сумасшедший для меня).

поэтому обходной путь очень прост:

AutoReleasePool := TNSAutoreleasePool.Create; 
try 
    ... do you code 
finally 
    AutoReleasePool.release; // << will free right now all the object 
end;  

теперь я не знаю, скорость штраф использования этого ...

Смежные вопросы