views:

5106

answers:

6

I'm trying to do a simple thing; read an image from the internet, save it to the app's documents directory on the iphone, and read it back from that file so that i can do other things with it later. Writing the file works fine but when i try to read it back i get an EXC_BAD_ACCESS error in GDB that i have no idea how to resolve. Here is what my code basically looks like:

-(UIImage *) downloadImageToFile {
NSURL * url = [[NSURL alloc] initWithString: self.urlField.text];

NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);

NSString *documentsDirectory = [paths objectAtIndex:0];

[paths release]
NSString * path = [documentsDirectory stringByAppendingString:@"/testimg.png"];

NSData * data = [[NSData alloc] initWithContentsOfURL:url];

[data writeToFile:path atomically:YES];

return [[UIImage alloc] initWithContentsOfFile:path];
}

The code fails in the return statement when i try to initialize the UIImage from the file. Any ideas?

Edit: neglected to add a release that was the problem in the code originally.

A: 

These errors occur when you are mismanaging memory (ie. an object is being released prematurely or similar)

Try doing something like the following..

UIImage *myImage = [[UIImage alloc] initWithContentsOfFile:path];
return [myImage autorelease];

I spent a lot of time experimenting whilst getting to grips with the concepts of release/autorelease. Sometimes the retain keyword needs to be played also (although probably not in this case)

Another option could be simply the path does not exist, or cannot be read from?

adam
I know that it exists, because i create the file and it is there in the filesystem. I'll play around some more with the memory management things to see what i can find.
Kevlar
take the slash off the path, and make sure it is in the project. doesn't matter if it is in that dir, but it has to be added to the project for you to access it.
Genericrich
This is incorrect-- you should be autoreleasing the returned value, but you should not keep is as an instance variable of the class.
Marc Charbonneau
A: 

Perhaps, initWithContentsOfFile doesn't take a path argument? Browse around at the different init methods for UIImage, I think there's a different one for accepting a path.

There also might be something fancier you have to do for making a path? I remember doing something with "bundles"? Sorry to be so vague, it's all I remember offhand.

Greg
A: 

take the slash off the path, and make sure it is in the project. doesn't matter if it is in that dir, but it has to be added to the project for you to access it.

Genericrich
I can't add the file to the project because its not there before i run the program; i'm saving the file after having read it from elsewhere.
Kevlar
Use NSString's filesystem path manipulation methods and you won't need to worry about if you should/shouldn't include the slash. It's not related to this problem, though.
Marc Charbonneau
+5  A: 

Your code shows a severe lack of knowledge of how memory management works in Objective-C. In addition to the EXC_BAD_ACCESS errors you're receiving, improper memory management also causes memory leaks which, on a small device like the iPhone, can lead to random crashes.

I recommend you give this a thorogh read:

Introduction to Memory Management Programming Guide for Cocoa

August
Thanks for the link. In my actual code i was trying to release paths when i wasn't explicitly alloc-ing it, which caused problems later on. And you're right, i'm just starting with obj-c and its definitely more complicated than i'd thought it'd be.
Kevlar
No problem, hope I didn't sound too harsh. That documentation is well worth the read. Good luck with your development!
August
I've been getting a lot of questions about EXC_BAD_ACCESS lately so I wrote this http://loufranco.com/blog/files/Understanding-EXC_BAD_ACCESS.html to explain it, with a list of debugging techniques. In this case (too many releases), Build and Analyze/scan-build probably would have flagged it. If not, enabling Zombies definitely would have.
Lou Franco
+1  A: 

Definitely give memory management rules a quick review. Nothing jumps out that would cause the error you're getting, but you're leaking all those objects your allocating. If you don't understand the retain/release pattern, chances are there's another spot in your code where you're not retaining an object properly, and that's whats causing the EXC_BAD_ACCESS error.

Also note that NSString has methods for dealing with filesystem paths, you should never have to worry about the separator yourself.

Marc Charbonneau
+7  A: 

One thing that helps me a lot is to have a breakpoint on objc_exception_throw. Anytime I'm about to get an exception thrown, I hit this breakpoint and I can debug back up the stack chain. I just leave this breakpoint enabled all the time in my iPhone projects.

To do this, in xcode go to near the bottom of the left pane "Groups & Files" and find "Breakpoints". Open it and click on Project Breakpoints and in the detail pane (top), you'll see a blue field labeled "Double-Click for Symbol." Double-click on it and enter "objc_exception_throw".

Next time you throw an exception, you'll stop and in the debugger, you can walk back up the stack chain to your code that caused the exception.

Jon Thomason
Thanks, this is a very useful tip.
NiKUMAN
I think this is now built in to Xcode, in the Run menu, "Stop on Objective-C Exceptions"
Lou Franco