Program received signal:EXC_BAD_ACCESS. What to do with this? - iphone

I just recently started learning Objective C/Cocoa and I know how important the memory management is and I believe this error I've been having is regarding to that.
I have a very very simple screen: two UITextView, one Button, one UILabel.
My header file has:
#interface PontaiViewController : UIViewController {
UITextField *loginField;
UITextField *passwordField;
UILabel *userID;
}
#property (nonatomic, retain) IBOutlet UITextField *loginField;
#property (nonatomic, retain) IBOutlet UITextField *passwordField;
#property (nonatomic, retain) IBOutlet UILabel *userID;
- (IBAction) btnLoginClicked:(id) sender;
The implementation has:
#implementation PontaiViewController
#synthesize loginField;
#synthesize passwordField;
#synthesize userID;
-(IBAction) btnLoginClicked:(id)sender {
NSString *string1 = #"username=";
NSString *string2 = [string1 stringByAppendingString:(loginField.text)];
NSString *string3 = [string2 stringByAppendingString:(#"&password=")];
NSString *post = [string3 stringByAppendingString:(passwordField.text)];
NSLog(#"The post is %#", post);
userID.text=loginField.text;
[string1 release];
[string2 release];
[string3 release];
[post release];
}
and it finishes with
- (void)viewDidUnload
{
[super viewDidUnload];
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
self.loginField=nil;
self.passwordField=nil;
self.userID=nil;
}
- (void) dealloc {
[super dealloc];
[loginField release];
[passwordField release];
[userID release];
}
When I run this demo, and try to write something in the TextView, I get this error.
What could it be?
Regards,
Felipe

Also, your NSStrings are autoreleased, and then you're releasing them again (over releasing). Read up on memory management of convenience methods.

stringByAppendingString returns an autoreleased object, don't release string1, string2, string3 and post.

In viewDidUnload you set loginField to nil, then you try to release it in dealloc. This isn't right. You only need to release valid items that you own.
Additionally, (as pointed out in a comment) you need to put [super dealloc] at the end of the dealloc function.
As pointed out by others, you also should not release the strings you're getting from stringByAppendingString.
Here are some basic rules about how to manage memory in Objective-C under iOS:
https://developer.apple.com/library/ios/#documentation/general/conceptual/devpedia-cocoacore/MemoryManagement.html
One thing you will find is that you only release stuff you are responsible for, and you're not responsible for it unless it was created with one of these:
alloc, allocWithZone:, copy, copyWithZone:, mutableCopy, mutableCopyWithZone

You should comment out the following
//[string1 release];
//[string2 release];
//[string3 release];
//[post release];
since you are using helper methods and not explicitly allocating anything.

Related

NSMutableArray with memory leak

I am using following code to create NSMutableArray. When I run the same in “Profile” mode, it is showing a memory leakage.
SampleArray.h
#interface SampleArray: NSObject {
}
#property (assign, retain) NSMutableArray *array;
#end
SampleArray.m
#import "SampleArray.h"
#implementation SampleArray
#synthesize array;
-(void) viewDidLoad {
self.array =[ [NSMutableArray alloc] init];
}
-(void) viewWillDisappear:(BOOL)animated {
[self.array release];
}
#end
When I am using autorelease, then I can’t able to access the same in other function or method and return null value. Please help me to find the issue.
releasing this array in viewWilLDisappear is not a good idea, you should release in the dealloc function. You should worry about over-releasing this item and causing a program crash since viewWilLDisappear may get called multiple times during the lifetime of this ViewController.
Anyhow, you are double retaining the item beacuse your property has a retain on it (and make it nonatomic, not assign), add an autorelease to your alloc/init:
self.array =[[[NSMutableArray alloc] init] autorelease];
and move
[array release];
to your dealloc function. Or convert to ARC and don't worry any longer...
Try setting it to (nonatomic, retain), then autoreleasing.
It is better to handle memory de-allocation in your -dealloc() and set your array to nil to be more secure in your -viewDidUnload()
so it will be:
-(void) viewDidUnload
{
self.array = nil;
}
-(void) dealloc
{
[array release];
[super dealloc];
}
and like other people said, declare your property as (nonatomic, retain) instead of (assign, retain)
First of all I'm assuming that you are using
#property (nonatomic, retain) NSMutableArray *array;
use this
-(void) viewDidLoad {
array =[[NSMutableArray alloc] init];
}
-(void) viewWillDisappear:(BOOL)animated {
[array release];
}
I will recommend you to use dealloc instead of viewWillDisappear
-(void) dealloc {
[array release];
[super dealloc];
}
Explanation of your code
-(void) viewDidLoad {
// here you are allocating a mutable array thus retain count becomes one
// then you are assigning it to the property which is retain and thus retains it
// making the retain count 2
self.array =[ [NSMutableArray alloc] init];
}
-(void) viewWillDisappear:(BOOL)animated {
// here you are releasing it so its retain count becomes 1 from 2
// thus shows memory leak
[self.array release];
}

ABTableViewCell and adding an image

For a view in my iPhone application, I am using a subclass of the ABTableViewCell (https://github.com/enormego/ABTableViewCell). It's a fairly simple cell, but I wanted to use this for the scrolling speed I need, because a lot of them can in the table at once.
Here is the header of the file:
#interface WHUserTableViewCell : ABTableViewCell {
NSString* Name;
NSString* DetailsText;
UIImage* UserImage;
}
#property (nonatomic, copy) NSString* Name;
#property (nonatomic, copy) NSString* DetailsText;
#property (nonatomic, copy) UIImage* UserImage;
I know that by using 'copy' on an image, I am only supporting iOS 4.2 and up, but that is something I might fix later.
I follow the way AteBits uses this cell, by creating custom set methods for the properties, like this:
- (void) setUserImage:(UIImage *) userImage
{
[UserImage release];
UserImage = [userImage copy];
[self setNeedsDisplay];
}
- (void) setName:(NSString *) name
{
[Name release];
Name = [name copy];
[self setNeedsDisplay];
}
- (void) setDetailsText:(NSString *) detailsText
{
[DetailsText release];
DetailsText = [detailsText copy];
[self setNeedsDisplay];
}
The images that are assigned to the 'UserImage' property, are coming from a Singleton class, which provides caching and downloading of the images. So that class should be the 'owner' of the images.
There is only one problem, once the cell deallocs, and I release all the properties the application crashes on the [UserImage release] line, here's my dealloc method:
- (void)dealloc
{
[super dealloc];
[UserImage release];
[Name release];
[DetailsText release];
}
This cell uses custom drawing, just like AteBits explains in his famous blog post about this. What is the correct and fastest way to handle images for this. I would like to continue using my singleton caching/downloading class to handle images, but I don't think that is the source of the problem, since I am copying the image objects.
[super dealloc]; should be the last line of - (void)dealloc.
Related: Why do I have to call super -dealloc last, and not first?

Using NSDate as a property gives me EXC_BAD_ACCESS, why?

I am adding NSDate as a pointer with a property, and every time I unload my view, it crashes with EXC_BAD_ACCESS. I am doing (not posting full code):
.h
NSDate *scheduledDate;
#property (nonatomic, retain) NSDate *scheduledDate;
.m
#synthesize scheduledDate;
- (void)dealloc {
[super dealloc];
[asset release];
[passedDate release];
[eventDate release];
[eventName release];
}
I have not done anything else with the pointer, but I still get EXC_BAD_ACCESS. Why is this happening? Is there a different way to set the property for NSDate?
SORRY:
I fixed an error in my question code, it was only a copy and paste issue, not a fix to my problem, it still exists.
You're calling [super dealloc] before the release in your dealloc implementation. That means the [scheduledDate release] is release some non-free memory (which is no longer nil).
Specifically, change the order so [super dealloc] is last:
- (void)dealloc {
[asset release];
[passedDate release];
[eventDate release];
[eventName release];
[super dealloc];
}
Your code looks inconsistent. The #property declaration should be for "NSDate scheduledDate", not "NSString ...".
If you are not using #property (nonatomic, retain) NSDate *scheduledDate; then there is no need to synthesize scheduledDate.
Also, how are you determining the value of scheduledDate? post the code you are using for it.
Also, post the crash log that your app produces.
Your #property (nonatomic, retain) is for "passedDate", not "scheduledDate". Since "scheduledDate" is not getting instantiated and retained by #property (nonatomic, retain), then attempting to release it is attempting to release something that hasn't been created yet (it isn't being synthesized as a property).

IS this class Many part of memory Leak

I am much confuse about my class.
Specially about Memory Management.
Please Guide me about NSString Concept at here.
My Class is.
#import <Foundation/Foundation.h>
#interface itinerary_detail : NSObject {
NSString *itinerary_title;
NSString *itinerary_creator;
NSString *itinerary_identifiere;
NSString *itinerary_created;
NSString *itinerary_modified;
}
#property (retain) NSString *itinerary_title;
#property (retain) NSString *itinerary_creator;
#property (retain) NSString *itinerary_identifiere;
#property (retain) NSString *itinerary_created;
#property (retain) NSString *itinerary_modified;
-(void) itinerary_initialization;
-(void) itinerary_title:(NSString *) xml_value;
-(void) itinerary_creator:(NSString *) xml_value;
-(void) itinerary_identifiere:(NSString *) xml_value;
-(void) itinerary_created:(NSString *) xml_value;
-(void) itinerary_modified:(NSString *) xml_value;
#end
and My .m class is
#import "itinerary_detail.h"
#implementation itinerary_detail
#synthesize itinerary_title,itinerary_creator,itinerary_identifiere,itinerary_created,itinerary_modified;
-(void) itinerary_initialization
{
itinerary_title=#"null";
itinerary_creator=#"null";
itinerary_identifiere=#"null";
itinerary_created=#"null";
itinerary_modified=#"null";
}
-(void) itinerary_title:(NSString *) xml_value
{
itinerary_title=xml_value;
}
-(void) itinerary_creator:(NSString *) xml_value
{
itinerary_creator=xml_value;
}
-(void) itinerary_identifiere:(NSString *) xml_value
{
itinerary_identifiere=xml_value;
}
-(void) itinerary_created:(NSString *) xml_value
{
itinerary_created=xml_value;
}
-(void) itinerary_modified:(NSString *) xml_value
{
itinerary_modified=xml_value;
}
-(void) dealloc
{
[itinerary_title release];
[itinerary_creator release];
[itinerary_identifiere release];
[itinerary_created release];
[itinerary_modified release];
[super dealloc];
}
#end
My question about.
1- Is this type Deceleration of NSString in this class of Memory Leak Issue. If Yes Please How i Will change this.
2- I am Using This class into Other class
Like that
itinerary_detail *check=[[itinerary_detail alloc] init];
[check itinerary_initialization];
[check release];
my question is this right way . or this is also a Memory Leak Issue.
Please Guide Me How to Deceleration Of this class and How to handle all memory Leak Issues.
Please Help Me
The problem come from the fact that you don't use the property but directly access the member variable. replace itinerary_title=xml_valueby self.itinerary_title=xml_value
btw, string properties are usually (copy) and not (retain) and why do you create all those methods while the synthesize will do it for you.
remove the methods from the .h file and from the .m file and set the property as
#property (copy) NSString* myString;
Your code shows that you need to get the basics of Cocoa and Objective-C right, before writing an actual program. Read Cocoa Fundamentals, OOP with Objective-C, etc. Resist the urge to start writing programs right now; the time you'll spend to learn the basics will greatly reduce your headache later.
Your code should look like:
#interface ItineraryDetail : NSObject {
NSString *itineraryTitle;
...
}
#property (retain) NSString *itineraryTitle;
#end
and
#implementation ItineraryDetail
#synthesize itineraryTitle, ... ;
-(id)init{
self=[super init];
if(self){
itineraryTitle=nil;
}
return self;
}
-(void) dealloc
{
[itineraryTitle release];
[super dealloc];
}
#end
and
ItineraryDetail *check=[[ItineraryDetail alloc] init];
... use it ...
[check release];
A few points:
In Objective-C, you don't usually name_like_this. You NameLikeThis. This is not an absolute rule, but it's customary, and you should follow it in general.
You don't write a method like ...Initialize separately. Rather, it's implemented using init, with [super init] inside it.
When you synthesize a property named foo via #synthesize foo, the setter setFoo: and the getter foo: are automatically generated, so you don't have to provide them manually. And you mistakenly used the name foo: for the setter! That will totally confuse the system.
The nil value for NSString (or any object in Objective-C in general) is not #"null" but just nil. And the ivars are set to nil automatically by the system, so you don't really do that in the initialization method.

IBOutlet, use of member properties or not? memory leak?

I have noticed that the memory usage of a program I wrote, keep increasing over time. XCode's instruments shows no memory leak, yet you can see the heap stack growing over time..
Upon investigation, a lot of the memory usage come from the IBOutlet UI objects. The interface is build with Interface Builder.
Typical usage would be like:
header:
#interface HelpViewController : UIViewController <UIWebViewDelegate> {
IBOutlet UIWebView *webView;
IBOutlet UIBarItem *backButton;
IBOutlet UIBarItem *forwardButton;
NSString *URL;
IBOutlet UIActivityIndicatorView *spin;
}
#property (nonatomic, retain) NSString *URL;
And for the usage :
- (void)webViewDidStartLoad:(UIWebView *)mwebView {
backButton.enabled = (webView.canGoBack);
forwardButton.enabled = (webView.canGoForward);
[spin startAnimating];
}
- (void)webViewDidFinishLoad:(UIWebView *)webView {
backButton.enabled = (webView.canGoBack);
forwardButton.enabled = (webView.canGoForward);
[spin stopAnimating];
}
Looking at the heap stack, you find that the UIActivityIndicatorView *spin object isn't properly deallocated, and its memory footprint will keep growing.
However, if I change the code to:
header:
#interface HelpViewController : UIViewController <UIWebViewDelegate> {
IBOutlet UIWebView *webView;
IBOutlet UIBarItem *backButton;
IBOutlet UIBarItem *forwardButton;
NSString *URL;
UIActivityIndicatorView *spin;
}
#property (nonatomic, retain) NSString *URL;
#property (nonatomic, assign) IBOutlet UIActivityIndicatorView *spin;
And in the code I do:
synthesize spin;
- (void)webViewDidStartLoad:(UIWebView *)mwebView {
backButton.enabled = (webView.canGoBack);
forwardButton.enabled = (webView.canGoForward);
[self.spin startAnimating];
}
- (void)webViewDidFinishLoad:(UIWebView *)webView {
backButton.enabled = (webView.canGoBack);
forwardButton.enabled = (webView.canGoForward);
[self.spin stopAnimating];
}
Nothing more, nothing else, then the heap stack doesn't grow anywhere as much.. and the UIActivityIndicatorView object doesn't leave any stuff behind
I can't figure out why it would make a difference here having an assign property or not, it just doesn't make sense ! Unless I massively misunderstood what's happening.
Any explanations would be welcomed..
Thanks
You need to release the objects in the dealloc method:
-(void)dealloc {
[webView release];
[backButton release];
[forwardButton release];
[URL release];
[spin release];
[super dealloc];
}
The reason why the problem doesn't occour in your second version is, that you set the property with the attribute assign, usually you should use retain for "object-properties" assign is usually used for the basic datatypes like int, float, bool etc...
EDIT:
to the part with retain and assign, afaik the behaviour is the following:
If the property is made with assign, then setting
self.thatVariable = something;
would be the same as:
thatVariable = something;
if you used retain it would be the same as:
[thatVariable release];
thatVariable = [something retain];
So if you used assign for variables that hold pointers to objects you can't be sure, that your object isnt deallocated somewhere else, which would result in a bad access.
Afaik the only reason to use assign with object is to get a weak reference. If you have to object which would both retain each other, none of it would ever get released. so thats a spot where you would use assign for objects. (f.e. often in the delegate-pattern. the object would retain it's delegate and the delegate would retain the object. In this case the delegate is often assigned)