получение EXC_BAD_ACCESS при назначении NSString

Я написал функцию для возврата строки в путь к каталогу. Я получаю EXC_BAD_ACCESS, и я думаю, что эта функция является причиной. Нужно ли сохранять nsstring или что-то в этом роде?

-(void) getRemoteFiles:(NSMutableArray *) M
{
    [self createFileToAppDirectory];

    if (!networkqueue) {
        networkqueue:[[[ASINetworkQueue alloc] init] autorelease];
    }

    [[self networkQueue] cancelAllOperations];

    [self setNetworkQueue:[ASINetworkQueue queue]];
    [[self networkQueue] setDelegate:self];
    [[self networkQueue] setRequestDidFinishSelector:@selector(requestFinished:)];
    [[self networkQueue] setRequestDidFailSelector:@selector(requestFailed:)];
    [[self networkQueue] setQueueDidFinishSelector:@selector(queueFinished:)];


    int i;

    for (i=0; i<[M count]; i++) {
        NSString *url=[M objectAtIndex:i];
        NSString* theFileName = [url lastPathComponent];
        NSString *safestring=[url stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
        if ([theFileName isEqualToString:@"nothing"]==NO) {

            ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:[NSURL URLWithString:safestring]];
            //think this is causing the problem
            NSString *savepath=[self getDirectoryPathForFileName:theFileName];
            //[request setDownloadDestinationPath:savepath];
            [[self networkQueue] addOperation:request];
        }

    }

    [[self networkQueue] go];
    //error thrown after this point


}
-(NSString *)getDirectoryPathForFileName:(NSString *)filename

{
    NSFileManager *filemgr;
    NSArray *dirPaths;
    NSString *docsDir;
    NSString *newDir;
    BOOL isDir;


    filemgr =[NSFileManager defaultManager];
    dirPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);

    docsDir = [dirPaths objectAtIndex:0];

    newDir = [docsDir stringByAppendingPathComponent:@"remix_data"];
    if ([filemgr fileExistsAtPath:newDir isDirectory:&isDir]==NO) {
        NSLog(@"dir should exist but does not... go funt dat");
    }

    NSString *localFilePath = [newDir stringByAppendingPathComponent:filename];
    [filemgr release];
    [docsDir release];
    [newDir release];
    return localFilePath;
}

person dubbeat    schedule 02.03.2011    source источник
comment
Вы не выполняете alloc/init для filemgr, docsDir и newDir. Так зачем вы их выпускаете?   -  person j_freyre    schedule 02.03.2011
comment
Я все еще изучаю управление памятью, и код взят из примера. Я так понимаю пример неправильный?   -  person dubbeat    schedule 02.03.2011


Ответы (3)


Нет, на самом деле ты слишком много отпускаешь. В getDirectoryPathForFileName вы освобождаете docsDir (например), хотя никогда не сохраняли его. Вы вытаскивали его из массива dirPaths, что не увеличит количество сохранений. Освобождая его, вы уменьшаете количество сохранений, возможно, до нуля, что освободит строку, пока массив все еще думает, что удерживает ее. В следующий раз, когда массив что-то сделает с этой строкой, ваше приложение рухнет. Просто удалите вызовы выпуска для docsDir и newDir, и все будет хорошо...

person Toastor    schedule 02.03.2011
comment
Я попробую это. Мое использование nsstring кажется вам приемлемым? - person dubbeat; 02.03.2011
comment
Да, мне это кажется вполне разумным, нет ни одного случая, чтобы вы использовали его без необходимости или неправильным образом. Вам просто нужно привыкнуть к этим проблемам с управлением памятью, но это не связано с NSString... Не бойтесь, вы к этому привыкнете! Одно эмпирическое правило: вам нужно выпускать что-то только в том случае, если вы создали его с помощью метода, начинающегося с init, или если вы сохранили его вручную. - person Toastor; 02.03.2011

Как всегда, когда у кого-то возникает проблема с EXC_BAD_ACCESS, я рекомендую NSZombie. В вашем конкретном случае довольно легко понять, почему он дает сбой, поскольку вы выпускаете материал без предварительного выделения или сохранения. Вы должны выпускать только то, что вы выделили или сохранили сами.

Если в будущем вы столкнетесь с проблемой EXC_BAD_ACCESS, это не так просто понять, вот как использовать NSZombie:

Чтобы активировать NSZombie, сделайте следующее:

  1. Получить информацию об исполняемом файле.
  2. Перейдите на вкладку «Аргументы».
  3. В разделе «Переменные для установки в среде:» добавьте:

Имя: NSZombieEnabled Значение: ДА

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

person Erik B    schedule 02.03.2011
comment
и не забудьте потом отключить зомби. Вы не хотите полчаса выискивать утечки только для того, чтобы выяснить, что вы оставили NSZombies включенным. Как я вчера. - person Matthias Bauch; 02.03.2011

Да, лучше сохранить строку и отпустить ее после использования. Также не рекомендуется освобождать строки docsDir и newDir, поскольку вы их не выделяете. Это объекты автоматического выпуска.

person visakh7    schedule 02.03.2011