Проблема управления памятью в Objective-C
Я создал графическое приложение, которое вызывает веб-сервис. Пользователь может масштабировать и перемещаться по графику, и программа время от времени принимает решение вызвать соответствующий веб-сервис для получения дополнительных данных. Это достигается с помощью следующего процесса:
Граф имеет цикл рендеринга, который постоянно рендерит граф, и некоторую логику принятия решений, которая добавляет информацию о вызовах веб-службы в стек.
Отдельный поток берет самую последнюю информацию о вызове веб-службы из стека и использует ее для выполнения вызова веб-службы. Другие объекты в стеке попадают в корзину.
Идея этого состоит в том, чтобы уменьшить количество обращений к веб-службам только до соответствующих и только по одному за раз.
Хорошо, с длинной историей в стороне (за что я извиняюсь), вот моя проблема управления памятью:
На графике есть постоянные (и соответственно заблокированные) объекты NSDate* для текущего отображаемого времени начала и окончания графика. Они передаются в инициализаторы для моих объектов запроса веб-службы. Объекты вызова веб-службы затем сохраняют даты.
После того, как вызовы веб-службы были сделаны (или заблокированы, если они устарели), они выпускают NSDate*.
Сам график высвобождает и перераспределяет новые NSDates* в событии "штрихи окончены".
Если при вызове removeAllObjects в стеке имеется только один объект вызова веб-службы, EXC_BAD_ACCESS возникает в методе освобождения объекта вызова веб-службы, когда он пытается освободить объекты даты (даже если они кажутся существующими и находятся в области действия в отладчике),
Однако, если я закомментирую сообщения об освобождении от деструктора, утечки памяти для одного объекта в стеке не происходит, но утечки памяти происходят, если в стеке более одного объекта.
Я понятия не имею, что происходит не так. Не имеет значения, какую символику хранилища я использую для дат вызова объектов веб-службы, так как они назначаются в инициализаторе, а затем только читаются (поэтому для корректности установлены только для чтения).
Это также, кажется, не имеет значения, если я сохраняю или копирую даты в инициализаторе (хотя все остальное явно выпадает из области видимости или случайно высвобождается в другом месте и вызывает сбой).
Мне жаль, что это объяснение слишком длинное, я надеюсь, что оно достаточно ясное, но я тоже не боюсь этого. Большое спасибо всем, кто может помочь, даже предложить что-нибудь, что я, возможно, пропустил?
Надеюсь, немного прояснить ситуацию, вот немного псевдо (ish) кода... вещи (исключая блокировки и инициализаторы):
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];
}
2 ответа
Безопаснее звонить [super dealloc]
последний в dealloc
, хотя и не обязательно. Возможно, что [super dealloc]
выпускает вещи, на которые полагаются другие вещи, такие как KVO.
Почему я должен вызывать super -dealloc последним, а не первым?
Проблема исправлена путём установки [super dealloc]; в конце desctructor. Благодарим Тун Ван Акера.
Из интереса; Кто-нибудь может сказать, применим ли тот же принцип к другим методам, таким как [super init]?