Arhn - архитектура программирования

Проблема с управлением памятью в Objective-C

Я создал графическое приложение, которое вызывает веб-службу. Пользователь может масштабировать и перемещать график, и программа время от времени принимает решение о вызове веб-службы для получения дополнительных данных. Это достигается следующим процессом:

Граф имеет цикл рендеринга, который постоянно отображает граф, и некоторую логику принятия решений, которая добавляет информацию о вызовах веб-службы в стек.

Отдельный поток берет самую последнюю информацию о вызове веб-службы из стека и использует ее для выполнения вызова веб-службы. Остальные объекты в стеке помещаются в корзину.

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

Правильно, без длинной истории (за что я извиняюсь), вот моя проблема с управлением памятью:

График имеет постоянные (и соответствующим образом заблокированные) объекты NSDate* для текущего отображаемого времени начала и окончания графика. Они передаются в инициализаторы для моих объектов запроса веб-службы. Затем объекты вызова веб-службы сохраняют даты.

После того, как вызовы веб-службы были выполнены (или помещены в корзину, если они устарели), они выпускают файл NSDate*.

Сам график выпускает и перераспределяет новые NSDates * по событию «завершение касания».

Если при вызове removeAllObjects в стеке находится только один объект вызова веб-службы, EXC_BAD_ACCESS возникает в методе освобождения объекта вызова веб-службы, когда он пытается освободить объекты даты (даже если они кажутся существующими и находятся в области действия в отладчике). .

Если, однако, я закомментирую сообщения об освобождении от деструктора, утечки памяти не произойдет для одного освобождаемого объекта в стеке, но утечка памяти произойдет, если в стеке более одного объекта.

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

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

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

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

NSMutableArray* requests;
NSDate* start, end;

-(void)webServiceThread
{
    if([requests count] > 1)
    {
        [self doRequestWithParams:[requests lastObject]];
        [requests removeAllObjects];
    }
}

-(void)render
{
    if(conditions for another web service call are met)
    {
        WebServiceRequest* new = [[WebServiceRequest alloc] initWithDates:start :end];
        [requests addObject:new];
        [new release];
    }

    [self doRendering];
}

-(void)touchesEnded
{
    [start release];
    [end release];
    start = [[NSDate dateSinceTimeInterval:chartLeft] retain];   //Ficticious NSDate Method names for example.
    end = [[NSDate dateSinceTimeInterval:chartRight] retain];
}

А затем в объекте вызова веб-службы:

NSDate* startDate;
NSDate* endDate;

-(void)initWithDates:start :end
{
    startDate = [start retain];
    endDate = [end retain];
}

-(void)dealloc
{
    [super dealloc];

    //The following two lines cause EXC_BAD_ACCESS if this is the only object on the request stack. If they are commented, however, memory is leaked if this is not the only object on the request stack.
    [startDate release];
    [endDate release];
}

  • Мне кажется, что есть один релиз для многих. Судя по вашему объяснению, неясно, где происходит этот дополнительный выпуск. Я думаю, что где-то по пути должен был прокрасться авторелиз, который вы пропустили. Было бы полезно, если бы вы могли опубликовать соответствующий код - все назначения, сохранение и выпуск дат. 22.04.2010
  • Небольшое замечание: обычно безопаснее вызывать [super dealloc] последним в dealloc, хотя это и не обязательно. stackoverflow.com/questions/909856/ 22.04.2010
  • Спасибо за ваш ответ, был добавлен псевдокод (фактический код значительно длиннее; это также может быть частью проблемы). Идея автоматического выпуска не пришла мне в голову, но у всего есть метод хранения (в настоящее время сохраняется), указанный там, где это применимо. 22.04.2010
  • Иисус сосал кровать; Ваше предложение поставить [super Dealloc] в конце фактически решило проблему!!! Это был очень длинный пост, но спасибо! 22.04.2010
  • Ну, я не вижу ничего плохого в вашем псевдокоде... Все, что приходит на ум, это то, что вы говорите даты readonly. Я предполагаю, что это означает, что вы используете для них свойства. Они readonly, retain? 22.04.2010
  • Я просто опубликую это как ответ, если вы не возражаете: P 22.04.2010

Ответы:


1

Безопаснее вызывать [super dealloc] последним в dealloc, хотя это и не обязательно. Возможно, что [super dealloc] выпускает вещи, на которые полагаются другие вещи, такие как KVO.

Почему я должен вызывать super - Dealloc последним, а не первым?

22.04.2010

2

Проблема исправлена ​​установкой [super Dealloc]; в конце деструктора. Кредит Toon Van Acker.

из интереса; Кто-нибудь может сказать, применим ли тот же принцип к другим методам, таким как [super init]?

22.04.2010
  • Вы ДОЛЖНЫ вызвать [super Dealloc] последним. Как только он вызывается, вы не можете гарантировать, что какой-либо из ваших ivars больше действителен, потому что [super Dealloc] в конечном итоге вызывает [NSObject Dealloc], который освобождает память и делает ее доступной для повторного использования. [super init] должен быть выполнен перед любым вашим собственным кодом инициализации и его возвращаемым значением, назначенным self. 22.04.2010
  • Новые материалы

    Коллекции публикаций по глубокому обучению
    Последние пару месяцев я создавал коллекции последних академических публикаций по различным подполям глубокого обучения в моем блоге https://amundtveit.com - эта публикация дает обзор 25..

    Представляем: Pepita
    Фреймворк JavaScript с открытым исходным кодом Я знаю, что недостатка в фреймворках JavaScript нет. Но я просто не мог остановиться. Я хотел написать что-то сам, со своими собственными..

    Советы по коду Laravel #2
    1-) Найти // You can specify the columns you need // in when you use the find method on a model User::find(‘id’, [‘email’,’name’]); // You can increment or decrement // a field in..

    Работа с временными рядами спутниковых изображений, часть 3 (аналитика данных)
    Анализ временных рядов спутниковых изображений для данных наблюдений за большой Землей (arXiv) Автор: Рольф Симоэс , Жильберто Камара , Жильберто Кейрос , Фелипе Соуза , Педро Р. Андраде ,..

    3 способа решить квадратное уравнение (3-й мой любимый) -
    1. Методом факторизации — 2. Используя квадратичную формулу — 3. Заполнив квадрат — Давайте поймем это, решив это простое уравнение: Мы пытаемся сделать LHS,..

    Создание VR-миров с A-Frame
    Виртуальная реальность (и дополненная реальность) стали главными модными терминами в образовательных технологиях. С недорогими VR-гарнитурами, такими как Google Cardboard , и использованием..

    Демистификация рекурсии
    КОДЕКС Демистификация рекурсии Упрощенная концепция ошеломляющей О чем весь этот шум? Рекурсия, кажется, единственная тема, от которой у каждого начинающего студента-информатика..