Почему я получаю EXC_BAD_ACCES - PullRequest
       16

Почему я получаю EXC_BAD_ACCES

0 голосов
/ 18 декабря 2009

Эй. Я работал над приложением Twitter и застрял на ошибке EXC_ BAD_ ACCESS в течение достаточно долгого времени. Я знаю, что EXC_ BAD_ ACCESS - это проблема с памятью, но я не могу точно определить, где проблема. Вот мой пример кода:

- (void)viewDidLoad {
   [super viewDidLoad];

   NSString *path = @"/Volumes/Schools/BHS/Student/740827/Documents/Forrest McIntyre CS193P/Presence2";
   NSArray *propList = [NSArray arrayWithContentsOfFile:[NSBundle pathForResource:@"TwitterUsers" ofType:@"plist" inDirectory:path]];

   people = [[NSMutableArray alloc]init];

   for (NSString *name in propList) {
     Person *p = [[Person alloc] initWithUserName: name];
     [people addObject: p];
     [p release];
   }
   // Uncomment the following line to display an Edit button in the navigation bar for this view controller.
   // self.navigationItem.rightBarButtonItem = self.editButtonItem;
}

Исключение выдается на последней скобке после комментария. Я верю, что он действительно где-то добавлен в цикл for, но просто обнаруживается при выходе.

Вот файл реализации для Person:

@implementation Person
@synthesize image;
@synthesize username;
@synthesize displayName;
@synthesize statusArray;

-(id)initWithUserName:(NSString *)userName {
 if(self = [super init])
 {
  self.username = userName;
  NSDictionary *info = [TwitterHelper fetchInfoForUsername:userName];
  self.displayName = [info objectForKey:@"name"];
  NSLog([NSString stringWithFormat:@"%@",[info objectForKey:@"profile_image_url"]]);
  NSString *imageURL2 = [NSString stringWithFormat:@"%@",[info objectForKey:@"profile_image_url"]];
  self.image = [UIImage imageWithData: [NSData dataWithContentsOfURL: [NSURL URLWithString: imageURL2]]];
  [info release];
  self.statusArray = [TwitterHelper fetchTimelineForUsername:userName]; 
 }
 return self;
}
@end

Спасибо за любую помощь

РЕДАКТИРОВАТЬ: Вот файл заголовка для PersonListViewController (класс, который содержит ViewDidLoad). Это просто, чтобы показать вам, откуда люди.

@interface PersonListViewController : UITableViewController {
    NSMutableArray *people;
}

@end

Ответы [ 8 ]

9 голосов
/ 18 декабря 2009

, поскольку вы никогда не сохраняете propList или path, вы не должны их отпускать.

Вы должны, однако, выпустить people

Обзор управления памятью см. Руководство по программированию управления памятью

Для быстрого исправления попробуйте статический анализатор.

3 голосов
/ 18 декабря 2009

Я думаю, что проблема здесь:

[propList release];

Поскольку вы создали propList с использованием arrayWithContentsOfFile, вам не нужно его выпускать - он будет автоматически выпущен. На самом деле, это авто-релиз, который вызывает ошибку, так как он пытается выпустить что-то, что вы уже выпустили вручную.

ETA: как упоминалось в коббале, вам также не нужно выпускать path.

1 голос
/ 21 декабря 2009

Для любых ошибок EXC_BAD_ACCESS вы обычно пытаетесь отправить сообщение освобожденному объекту. ЛУЧШИЙ способ отследить это - использовать NSZombieEnabled .

Это работает, фактически никогда не освобождая объект, а заключая его в «зомби» и устанавливаяфлаг внутри, который говорит, что обычно он был бы выпущен.Таким образом, если вы попытаетесь получить к нему доступ снова, он все еще будет знать, что было до того, как вы допустили ошибку, и с этим небольшим количеством информации вы обычно можете вернуться назад, чтобы увидеть, в чем проблема.

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

ОЧЕНЬ ВАЖНО ЗАМЕЧАТЬ однако вам необходимо на 100% убедиться, что это только в вашем коде отладки ине ваш код распространения.Поскольку ничего не выпущено, ваше приложение будет течь и течь и течь.Чтобы напомнить мне сделать это, я поместил этот журнал в своем приложении applelegate:

if(getenv("NSZombieEnabled") || getenv("NSAutoreleaseFreedObjectCheckEnabled"))
  NSLog(@"NSZombieEnabled/NSAutoreleaseFreedObjectCheckEnabled enabled!");

Если вам нужна помощь в поиске точной строки, выполните Build-and-Debug ( CMD-Y )) вместо Build-and-Run ( CMD-R ).Когда приложение падает, отладчик покажет вам, какая именно строка и в сочетании с NSZombieEnabled, вы сможете точно узнать, почему.

1 голос
/ 18 декабря 2009

Во-первых, ни один из них не необходим в вашем примере:

 [path release];
 [propList release];

, потому что:

path - строковый литерал (всегда будет существовать)

propList автоматически выпущен

1 голос
/ 18 декабря 2009

Отладка EXC_BAD_ACCESS трудно отладить. Это происходит, когда сообщение отправляется объекту, который уже освобожден. Вам необходимо выяснить, что является причиной этой общей ошибки, включив переменную среды NSZombiEnabled, чтобы среда Objective C могла «отслеживать» освобожденный объект. Используя это, когда вы получаете ошибку, вы можете определить, где произошла ошибка, посмотрев на стек вызовов. Вы не будете знать, где это выпущено, но по крайней мере это приблизит вас.

У меня не настроено здесь, но вы также можете передавать указатель на ошибку, из-за которой объект не сохраняется как зомби / пустышка.

Суть в том, что вам нужно убедиться, что переменные, которые вы хотите освободить, сохраняют их по мере необходимости.

В этом техническом разделе вопросов и ответов Apple даются советы по Нахождению ошибок с помощью EXC_BAD_ACCESS .

0 голосов
/ 21 декабря 2009

Пара вещей.

  • В initWithUserName: вы получаете информацию от метода, который не содержит alloc / copy / create. Кроме того, вы не сохраняете это явно. И все же вы отпускаете это. Это проблематично, если предположить, что fetchInfoForUsername: автоматически выпускает свой результат в соответствии с правилами управления памятью какао.

  • Использование методов доступа к свойствам в инициализаторах считается дурным тоном, поскольку это может привести к отправке уведомлений KVO для полуготового экземпляра.

0 голосов
/ 21 декабря 2009

что такое self.editButtonItem? Я не вижу его в вашем .h файле

0 голосов
/ 18 декабря 2009

http://www.cocoadev.com/index.pl?NSZombieEnabled может быть полезно для отслеживания ошибок EXC_BAD_ACCESS. Вместо того, чтобы освобождать объекты, когда они release d, они переводят их в состояние зомби, которое вызывает исключение при последующем обращении к ним. Только убедитесь, что никогда не выпускаете код с этим установленным флагом, так как он будет пропускать память как сито.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...