Reputation: 117
When scrolling through table, my application crash and console said it was EXC_BAD_ACCESS
.
I've look everywhere, and people suggest me to use NSZombieEnabled
on my executables environment variables. I've set NSZombieEnabled
, NSDebugEnabled
, MallocStackLogging
and MallocStackLoggingNoCompact
to YES on my executables.
But apparently i still can't figure out which part of my program that cause EXC_BAD_ACCESS. This is what my console said
[Session started at 2010-12-21 21:11:21 +0700.]
GNU gdb 6.3.50-20050815 (Apple version gdb-1510) (Wed Sep 22 02:45:02 UTC 2010)
Copyright 2004 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB. Type "show warranty" for details.
This GDB was configured as "x86_64-apple-darwin".sharedlibrary apply-load-rules all
Attaching to process 9335.
TwitterSearch(9335) malloc: recording malloc stacks to disk using standard recorder
TwitterSearch(9335) malloc: process 9300 no longer exists, stack logs deleted from /tmp/stack-logs.9300.TwitterSearch.suirlR.index
TwitterSearch(9335) malloc: stack logs being written into /tmp/stack- logs.9335.TwitterSearch.tQJAXk.index
2010-12-21 21:11:25.446 TwitterSearch[9335:207] View Did Load
Program received signal: “EXC_BAD_ACCESS”.
And this is when i tried to type backtrace
on gdb :
Program received signal: “EXC_BAD_ACCESS”.
(gdb) backtrace
#0 0x00f20a67 in objc_msgSend ()
#1 0x0565cd80 in ?? ()
#2 0x0033b7fa in -[UITableView(UITableViewInternal) _createPreparedCellForGlobalRow:withIndexPath:] ()
#3 0x0033177f in -[UITableView(UITableViewInternal) _createPreparedCellForGlobalRow:] ()
#4 0x00346450 in -[UITableView(_UITableViewPrivate) _updateVisibleCellsNow:] ()
#5 0x0033e538 in -[UITableView layoutSubviews] ()
#6 0x01ffc451 in -[CALayer layoutSublayers] ()
#7 0x01ffc17c in CALayerLayoutIfNeeded ()
#8 0x01ff537c in CA::Context::commit_transaction ()
#9 0x01ff50d0 in CA::Transaction::commit ()
#10 0x020257d5 in CA::Transaction::observer_callback ()
#11 0x00d9ffbb in __CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__ ()
#12 0x00d350e7 in __CFRunLoopDoObservers ()
#13 0x00cfdbd7 in __CFRunLoopRun ()
#14 0x00cfd240 in CFRunLoopRunSpecific ()
#15 0x00cfd161 in CFRunLoopRunInMode ()
#16 0x01a73268 in GSEventRunModal ()
#17 0x01a7332d in GSEventRun ()
#18 0x002d642e in UIApplicationMain ()
#19 0x00001d4e in main (argc=1, argv=0xbfffee34) at /Users/suprie/Documents/Projects/Self/cocoa/TwitterSearch/main.m:14
I really appreciate for any clue to help me debug my application.
EDIT this is the Header file of table
#import <UIKit/UIKit.h>
@interface TwitterTableViewController : UITableViewController {
NSMutableArray *twitters;
}
@property(nonatomic,retain) NSMutableArray *twitters;
@end
and the implementation file
#import "TwitterTableViewController.h"
@implementation TwitterTableViewController
@synthesize twitters;
#pragma mark -
#pragma mark Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
// Return the number of sections.
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
// Return the number of rows in the section.
return [twitters count];
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
return 90.0f;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
const NSInteger TAG_IMAGE_VIEW = 1001;
const NSInteger TAG_TWEET_VIEW = 1002;
const NSInteger TAG_FROM_VIEW = 1003;
static NSString *CellIdentifier = @"Cell";
UIImageView *imageView;
UILabel *tweet;
UILabel *from;
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
// Image
imageView = [[[[UIImageView alloc] initWithFrame:CGRectMake(5.0f, 5.0f, 60.0f, 60.0f)] autorelease] retain];
[cell.contentView addSubview:imageView];
imageView.tag = TAG_IMAGE_VIEW;
// Tweet
tweet = [[[UILabel alloc] initWithFrame:CGRectMake(105.0f, 5.0f, 200.0f, 50.0f)] autorelease];
[cell.contentView addSubview:tweet];
tweet.tag = TAG_TWEET_VIEW;
tweet.numberOfLines = 2;
tweet.font = [UIFont fontWithName:@"Helvetica" size:12];
tweet.textColor = [UIColor blackColor];
tweet.backgroundColor = [UIColor clearColor];
// From
from = [[[UILabel alloc] initWithFrame:CGRectMake(105.0f, 55.0, 200.0f, 35.0f)] autorelease];
[cell.contentView addSubview:from];
from.tag = TAG_FROM_VIEW;
from.numberOfLines = 1;
from.font = [UIFont fontWithName:@"Helvetica" size:10];
from.textColor = [UIColor blackColor];
from.backgroundColor = [UIColor clearColor];
}
// Configure the cell...
NSMutableDictionary *twitter = [twitters objectAtIndex:(NSInteger) indexPath.row];
// cell.text = [twitter objectForKey:@"text"];
tweet.text = (NSString *) [twitter objectForKey:@"text"];
tweet.hidden = NO;
from.text = (NSString *) [twitter objectForKey:@"from_user"];
from.hidden = NO;
NSString *avatar_url = (NSString *)[twitter objectForKey:@"profile_image_url"];
NSData * imageData = [[NSData alloc] initWithContentsOfURL: [NSURL URLWithString: avatar_url]];
imageView.image = [UIImage imageWithData: imageData];
imageView.hidden = NO;
return cell;
}
#pragma mark -
#pragma mark Table view delegate
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
NSMutableDictionary *twitter = [twitters objectAtIndex:(NSInteger)indexPath.row];
NSLog(@"Twit ini kepilih :%@", [twitter objectForKey:@"text"]);
}
#pragma mark -
#pragma mark Memory management
- (void)didReceiveMemoryWarning {
// Releases the view if it doesn't have a superview.
[super didReceiveMemoryWarning];
}
- (void)viewDidUnload {
}
- (void)dealloc {
[super dealloc];
}
@end
this is viewDidLoad from myViewController :
- (void)viewDidLoad {
NSLog(@"View Did Load");
[super viewDidLoad];
twitterTableController = [[TwitterTableViewController alloc] init];
responseData = [[NSMutableData data] retain];
UIView *mView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 320, 480)];
mView.backgroundColor = [UIColor whiteColor];
theTableView = [[[UITableView alloc] initWithFrame:CGRectMake(0, 0, 320, 480)] autorelease];
theTableView.delegate = twitterTableController;
theTableView.dataSource = twitterTableController;
UIBarButtonItem *rightButton = [[[UIBarButtonItem alloc] initWithTitle:@"Refresh" style:UIBarButtonItemStyleDone target:self action:@selector(refreshResult)] autorelease];
self.navigationItem.rightBarButtonItem = rightButton;
// [mView addSubview:label];
self.view = mView;
[self.view addSubview:theTableView];
NSString *url = @"http://search.twitter.com/search.json?q=suprie";
NSURLRequest *theRequest=[NSURLRequest requestWithURL:[NSURL URLWithString:url]
cachePolicy:NSURLRequestUseProtocolCachePolicy
timeoutInterval:60.0];
[[NSURLConnection alloc] initWithRequest:theRequest delegate:self];
}
[UPDATE] I've tried Instrument to locate the problem. My friend said, if it was a Zombie, Instrument would tell me. The problem is, when the program crash the instrument didn't say anything.
I've also remove all autorelease. still the program crash. I've managed to use malloc_history and the result was
(gdb) shell malloc_history 10433 0x0552bfc0
malloc_history Report Version: 2.0
Process: TwitterSearch [10433]
Path: /Users/suprie/Library/Application Support/iPhone Simulator/4.2/Applications/AF5C1948-C3DC-4680-9023- 4C3DFE8A5E13/TwitterSearch.app/TwitterSearch
Load Address: 0x1000
Identifier: TwitterSearch
Version: ??? (???)
Code Type: X86 (Native)
Parent Process: gdb-i386-apple-darwin [10435]
Date/Time: 2010-12-21 23:28:41.144 +0700
OS Version: Mac OS X 10.6.5 (10H574)
Report Version: 6
ALLOC 0x552bfc0-0x552bfd7 [size=24]: thread_18d9540 |start | main | UIApplicationMain | GSEventRun | GSEventRunModal | CFRunLoopRunInMode | CFRunLoopRunSpecific | __CFRunLoopRun | __CFRunLoopDoSources0 | __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ | MultiplexerSource::perform() | URLConnectionClient::processEvents() | URLConnectionClient::ClientConnectionEventQueue::processAllEventsAndConsumePayload(XConnectionEventInfo<XClientEvent, XClientEventParams>*, long) | URLConnectionClient::ClientConnectionEventQueue::processAllEventsAndConsumePayload(XConnectionEventInfo<XClientEvent, XClientEventParams>*, long) | URLConnectionClient::_clientDidFinishLoading(URLConnectionClient::ClientConnectionEventQueue*) | _NSURLConnectionDidFinishLoading | -[NSURLConnection(NSURLConnectionReallyInternal) sendDidFinishLoading] | -[TwitterViewController connectionDidFinishLoading:] | -[NSString(NSString_SBJSON) JSONValue] | -[SBJsonParser objectWithString:] | -[SBJsonParser scanValue:] | -[SBJsonParser scanRestOfDictionary:] | -[SBJsonParser scanValue:] | -[SBJsonParser scanRestOfArray:] | +[NSMutableArray arrayWithCapacity:] | -[__NSPlaceholderArray initWithCapacity:] | +[__NSArrayM __new::] | __CFAllocateObject2 | class_createInstance | _internal_class_createInstanceFromZone | calloc | malloc_zone_calloc
But i couldn't read it. I don't understand which line that made my apps crash
[FIXED] I've fixed the error.. here's the new CellforRowatIndexPath
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
const NSInteger TAG_IMAGE_VIEW = 1001;
const NSInteger TAG_TWEET_VIEW = 1002;
const NSInteger TAG_FROM_VIEW = 1003;
static NSString *CellIdentifier = @"Cell";
UIImageView *imageView;
UILabel *lblTweet;
UILabel *from;
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
imageView = [[UIImageView alloc] initWithFrame:CGRectMake(5.0f, 5.0f, 60.0f, 60.0f)];
[cell.contentView addSubview:imageView];
imageView.tag = TAG_IMAGE_VIEW;
// Tweet
lblTweet = [[UILabel alloc] initWithFrame:CGRectMake(105.0f, 5.0f, 200.0f, 50.0f)] ;
[cell.contentView addSubview:lblTweet];
lblTweet.tag = TAG_TWEET_VIEW;
lblTweet.numberOfLines = 2;
lblTweet.font = [UIFont fontWithName:@"Helvetica" size:12];
lblTweet.textColor = [UIColor blackColor];
lblTweet.backgroundColor = [UIColor clearColor];
// From
from = [[UILabel alloc] initWithFrame:CGRectMake(105.0f, 55.0, 200.0f, 35.0f)] ;
[cell.contentView addSubview:from];
from.tag = TAG_FROM_VIEW;
from.numberOfLines = 1;
from.font = [UIFont fontWithName:@"Helvetica" size:10];
from.textColor = [UIColor blackColor];
from.backgroundColor = [UIColor clearColor];
}else{
// I add this to fix the error
imageView = (UIImageView *) [[cell viewWithTag:TAG_IMAGE_VIEW] retain];
lblTweet = (UILabel *)[cell viewWithTag:TAG_TWEET_VIEW];
from = (UILabel *)[cell viewWithTag:TAG_FROM_VIEW];
}
NSMutableDictionary *twitter = [twitters objectAtIndex:(NSInteger) indexPath.row];
NSString *textTweet = (NSString *) [twitter objectForKey:@"text"];
lblTweet.text = textTweet;
lblTweet.hidden = NO;
from.text = (NSString *) [twitter objectForKey:@"from_user"];
from.hidden = NO;
NSString *avatar_url = (NSString *)[twitter objectForKey:@"profile_image_url"];
NSData * imageData = [[NSData alloc] initWithContentsOfURL: [NSURL URLWithString: avatar_url]];
imageView.image = [UIImage imageWithData: imageData];
imageView.hidden = NO;
return cell;
}
Somehow when i scroll up, the apps redraw the table, and since the cell was drawn before, the table and anything else not initialized properly and throw "EXC_BAC_ACCESS".
Thank you so much for your help :D
Upvotes: 2
Views: 9513
Reputation: 117
I've fixed the error , and locate where the program crashed
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
const NSInteger TAG_IMAGE_VIEW = 1001;
const NSInteger TAG_TWEET_VIEW = 1002;
const NSInteger TAG_FROM_VIEW = 1003;
static NSString *CellIdentifier = @"Cell";
UIImageView *imageView;
UILabel *lblTweet;
UILabel *from;
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
imageView = [[UIImageView alloc] initWithFrame:CGRectMake(5.0f, 5.0f, 60.0f, 60.0f)];
[cell.contentView addSubview:imageView];
imageView.tag = TAG_IMAGE_VIEW;
// Tweet
lblTweet = [[UILabel alloc] initWithFrame:CGRectMake(105.0f, 5.0f, 200.0f, 50.0f)] ;
[cell.contentView addSubview:lblTweet];
lblTweet.tag = TAG_TWEET_VIEW;
lblTweet.numberOfLines = 2;
lblTweet.font = [UIFont fontWithName:@"Helvetica" size:12];
lblTweet.textColor = [UIColor blackColor];
lblTweet.backgroundColor = [UIColor clearColor];
// From
from = [[UILabel alloc] initWithFrame:CGRectMake(105.0f, 55.0, 200.0f, 35.0f)] ;
[cell.contentView addSubview:from];
from.tag = TAG_FROM_VIEW;
from.numberOfLines = 1;
from.font = [UIFont fontWithName:@"Helvetica" size:10];
from.textColor = [UIColor blackColor];
from.backgroundColor = [UIColor clearColor];
}else{
// I add this to fix the error
imageView = (UIImageView *) [[cell viewWithTag:TAG_IMAGE_VIEW] retain];
lblTweet = (UILabel *)[cell viewWithTag:TAG_TWEET_VIEW];
from = (UILabel *)[cell viewWithTag:TAG_FROM_VIEW];
}
NSMutableDictionary *twitter = [twitters objectAtIndex:(NSInteger) indexPath.row];
NSString *textTweet = (NSString *) [twitter objectForKey:@"text"];
lblTweet.text = textTweet;
lblTweet.hidden = NO;
from.text = (NSString *) [twitter objectForKey:@"from_user"];
from.hidden = NO;
NSString *avatar_url = (NSString *)[twitter objectForKey:@"profile_image_url"];
NSData * imageData = [[NSData alloc] initWithContentsOfURL: [NSURL URLWithString: avatar_url]];
imageView.image = [UIImage imageWithData: imageData];
imageView.hidden = NO;
return cell;
}
Somehow when i scroll up, the apps redraw the table, and since the cell was drawn before, the table and anything else not initialized properly and throw "EXC_BAC_ACCESS".
Upvotes: 0
Reputation: 8280
I think your error come from that line :
imageView = [[[[UIImageView alloc] initWithFrame:CGRectMake(5.0f, 5.0f,60.0f, 60.0f)] autorelease] retain];
or from that line :
UIBarButtonItem *rightButton = [[[UIBarButtonItem alloc] initWithTitle:@"Refresh" style:UIBarButtonItemStyleDone target:self action:@selector(refreshResult)] autorelease];
The problem is maybe in the viewDidLoad method and I think it's in the previous line.
There are 2 mistakes in your code :
You are calling an autorelease to the objects imageView and rightButton. Autorelease means that you lost ownership on your object and he is put in pool waiting to be deallocated by the system. At anytime he can be "garbaged" by the system. So you should not make hypothesis on a "autorelease" object. So you the next time, you can imageView, maybe, at that time, it has been already released by the system :
[cell.contentView addSubview:imageView];
imageView.tag = TAG_IMAGE_VIEW;
You also call retain on that object, it means that you take ownership on that object. That doesn't make any sens because you called an autorelease before. You take ownership of an object if you create it using a method whose name begin or contains "alloc", "new", "copy" or send a retain message to that object.
The correct way to do that :
imageView = [[UIImageView alloc] initWithFrame:CGRectMake(5.0f, 5.0f, 60.0f, 60.0f)];
[cell.contentView addSubview:imageView];
imageView.tag = TAG_IMAGE_VIEW;
....
[imageView release];
///////
UIBarButtonItem *rightButton = [[UIBarButtonItem alloc] initWithTitle:@"Refresh" style:UIBarButtonItemStyleDone target:self action:@selector(refreshResult)];
...
[rightButton release];
You can find more information here about memory management rules in iOS : Memory Management rules
Upvotes: 1
Reputation:
where are you mutating the twitters
array? you should put in your viewDidLoad method this line:
twitters = [[NSMutableArray alloc]init];
and then setting or changing it. You can debug your code by NSLog'ing your cellForRowAtIndexPath
and see if the twitters
array still exist
Upvotes: 0
Reputation: 5671
So from the stack trace, it appears that it's crashing when it's trying to update the visible cells. BAD_ACCESS is usually a sign for an object that's gone, i.e. release.
I suspect that you've released a variable in your cellForRowAtIndex
method that you shouldn't have. Try to see if build and analyze in XCode gives you any hint, otherwise just try and remove all releases for debugging.
If you can post the method, we can have a look at it and maybe help you. Memory Management in Objective-c ain't the easiest thing...
[edit] looking at your code, I can't see any issues. I'm really puzzeld as to why you'd get the the error you have. For starters, i'd remove all the autoreleases and the random retain at uiimage view and check if that helps. Maybe somebody else can find the actual issue.
Upvotes: 0
Reputation: 6255
EXC_BAD_ACCESS can be caused by the AutoRelease pool attempting to release something that has already been explicitly released.
Without being able to see your code I would look at what your are releasing in your code ( [something release]; ) and see if you need to actually have to release it or not. If you find something that is suspect just comment it out and run your app again. If you get the same error you know that wasn't it.
Upvotes: 1
Reputation: 29925
an EXC_BAD_ACCESS occurs when you're trying to access a variable out of scope.
Try and retain
variables you are using in your tableView methods after you create them and you'll soon find out whats being released early/is out of scope.
I always get this when trying to use an auto release method with a global variable.
Eg: if you have @property (nonatomic, retain) NSString *aString;
then using aString = [NSString stringWithFormat:@"Some string"];
is going to auto release at the next run cycle and thus you won't be able to access that object later on, even though you think its a global variable.
Upvotes: 0