'EXC_BAD_ACCESS' When trying to access a variable? - objective-c

I get an 'EXC_BAD_ACCESS' error when trying to access variable in a function other than the one it was set in
The variable is set in the 'awakeFromNib' function:
//Retrieve Session-ID
sessionID = [self getSessionID];
And accessed in 'searchBtnClick':
NSLog(#"Commening search (%#)",sessionID); // This causes the error
The variable itself is defined in the header:
NSString *sessionID;
Can someone suggest what might be wrong with that?
The part which of getSessionID which returns the value:
NSString *pC = #"";
// Separate Session ID
pC = [initCookie substringFromIndex:10];
pC = [pC substringToIndex:32];
NSLog(#"Got session ID : %#",pC);
return pC;

Your -getSessionID method is returning an autoreleased variable—when you try to access the pointer again later, the string's already been deallocated and so the reference is no longer valid. You need to call -retain on the variable when you first retrieve it, like this:
sessionID = [[self getSessionID] retain];
Then, later, in your class's -dealloc, you need to balance the retain with a release:
[sessionID release];

If getSessionID follows normal Cocoa conventions, it returns an autoreleased object. You need to retain it, or sessionID will become a dangling pointer as soon as the autorelease pool is drained (probably at the end of the event loop).
If you are new to Objective C and Cocoa, you should make sure to read the Apple documentation about the memory model.

I had similar prob, it crashes when you have not allocated any memory. Releasing it like this:
UIImage *lObj_image = [UIImage imageNamed: #"bluebar.png"];
.
.
.
[lObj_image release];
Check in your viewdidload()

Related

assign NSString

I have an NSString called animation, which is called with the following (working) code:
animation=[rowInDataBase objectAtIndex:2] ;
NSLog(#"animation:%#",animation);
When I try to perform the following :
previousAnimation=animation;
The previousAnimation is assigned ccsprite.
When I try to logging previousAnimation to check its value with NSLog(#"previous-animation:%#",previousAnimation);, the application crashes unless previousAnimation is NULL
What am I doing wrong in my assignment ?
animation needs to be properly retained. You should create a property with a retain attribute for animation and previousAnimation and set them like this.
self.animation = [rowInDatabase objectAtIndex:2];
...
self.previousAnimation = self.animation;
Now both values will be properly retained between calls you will no longer have crashing issues. Just remember to release both values in dealloc.
Are you trying to copy the string? If so you should be doing:
NSString* previousAnimation = [NSString stringWithString:animation]; // autoreleased
or
NSString* previousAnimation = [animation copy]; // retain count 1, need to release
otherwise you should retain
previousAnimation = [animation retain];
and release previousAnimation when you are done.
It sounds like you're assigning a variable that has already been released, so the memory's being reused by some other random object (in the case you mentioned, a ccsprite object perhaps). But it's hard to tell for sure without seeing the code in more context.

Releasing a pointer causes program to crash, even though the variable isn't used

I'm still slogging through learning memory allocation and Objective-C (my first run with Leaks was unpretty, at best). Here is a current issue, I hope everyone can understand it, I've used some pseudo-code, but I don't believe I've left anything out.
I have a Row Class set for some database stuff, we'll use this:
#interface Row : NSObject {
int rowID;
NSString *firstName;
NSString *lastName;
}
I have a getRow function in my database class that looks something like this:
-(Row *) getRow
{
rowPlaceholder = [[Row alloc] init];
...
rowPlaceholder.rowID = column1;
rowPlaceholder.firstName = column2;
rowPlaceholder.lastName = column3;
...
return [rowPlaceholder autorelease]; //<-----Problem is happening here
}
Now in my ViewController I have 2 functions of importance to this situation:
-(void) viewWillAppear:(BOOL)animated{
currentRow = [[Row alloc] init];
currentRow = getRow;
firstNamelabel.text = currentRow.firstName;
}
The second function is a button the gets the second word:
-(IBAction)btnLastName:(id)sender{
lastNamelabel.text = currentRow.lastName; //<---Crashes the program
}
So, as you can see, using currentRow against causes the program to crash, and what I can't understand is that if I don't release rowPlaceholder the program works fine. At this point why does currentRow care about the data from another function, since it already has what it want (a value from getRow()).
What's going on here?
currentRow = [[Row alloc] init];
currentRow = getRow;
You create a row, then overwrite it with... I don't even know what getRow is in this context. There's no way this is compiling without warnings. Anyway, try using:
currentRow = [[self getRow] retain];
(Although, for the sake of convention, you should call the method just row.)
Without seeing the rest of your getRow method or Row class, I can't tell why the problem would be happening there.
autorelease means that the object in question will be automatically released. When this occurs is tied to when the autorelease pool is emptied, but for the default case it's when the UI "comes up for air" -- when your call chain returns back to the UI system code. If you're going to hold something "across" such a return to UI system code, you need to have it explicitly retained. In general, making it a retained property is the best way to do this (though of course you need to clear/release the property in your dealloc method).
[And why do you do this:]
currentRow = [[Row alloc] init];
currentRow = getRow;
When you allocate and init rowPlaceholder and then return it as autoreleased, that means its effectively ready to be cleaned up by memory management unless some other object retains it.
In the line:
currentRow=getRow
you are getting a copy of the pointer to the object returned by getRow but do not appear to be retaining it. (and getRow is autoreleasing it before returning it).
If currentRow is a property of your class then you need to refer to it as this.currentRow to ensure the accessor method is called (and it must be declared as a retain property). if its not declared as a property and is just an attribute of your class then you need to retain it manually.
The first time you reference currentRow.firstName is ok because there has been no loss of control by the current execution thread so the autorelease pool hasn't cleaned up this memory yet.
But once your thread loses control and give memory management a chance to clean it up, when you come back into the the btnLastName method the memory pointed to by currentRow (which is a pointer to the original memory allocated in the rowPlaceHolder = [[row alloc] init] call) has been released.

big memory problem in objective c

i've a function like this:
#property(nonatomic,retain) NSMutableArray *array;
#synthesize array = _array;
(NSMutableArray *) name
{
self.array = [[NSMutableArray alloc]init];
[_array addObject:object];
[object release];
return [_array autorelase];
}
In the other function i've a property like the property above, named result, and i make:
self.result = [... name];
Then in dealloc i make
[_result release];
and it crashes in this point, how can i solve this?
I've tried many roads, but or it crashes, or i see memory leak in Instruments, where am i wronging?
Thanks.
While there's a lot wrong with this code, the likely cause of your crash is that you're releasing object within -name without taking ownership of it- unless you're creating object within the method through a call to -alloc, -new, or -copy, that method doesn't own it and isn't responsible for releasing it. This is causing that object to be invalid within the NSMutableArray, so when _result releases, it attempts to release an invalid piece of memory and crashes.
Also, properties aren't simply local variables for individual functions, they're member variables for instances of the class for which you're writing these classes. If your end goal is only to return an autoreleased array and set it to result you could do the following:
- (NSMutableArray *) name {
//call a convenience method- it comes back autoreleased
NSMutableArray* theArray = [NSMutableArray array];
[theArray addObject:object];
//don't release object unless you took ownership of it in this function
return theArray;
}
then outside the function, either call self.result = [... name] or [self setResult:[... name]];
You have a very strange method definition (the header should have a - before the return type), and inside that definition you are accessing a variable called object that doesn't seem to exist. I'm not sure what you want, but you've got at least one memory problem. The array that you create in name gets leaked every time the method is called. If you add some details, like the crash message, someone may be able to help more.

properly creating object in objective-c for avoiding memory leaks

after having spent few months in trying to master the syntax and rules, I am going deeper in memory management rules.
One thing I do not understand and causing me confusion is how one creates objects.
Based on what stated in apple memory management guide, the following is a valid approach:
– (NSArray *)sprockets {
NSArray *array = [NSArray arrayWithObjects:mainSprocket,auxiliarySprocket, nil];
return array;
}
because I am not causing any memory leaks.
The reason why is that it's not using alloc for creating array and therefore sprockets is not the owner.
However I am wondering now what's inside arrayWithObjects.
Because it happens that in my apps I often have factory for creating custom objects using something similiar to:
return [[MyObject alloc] initWithParameter:(id)params]; // possible leak
If I want to change with a static method like:
return [MyObject initWithParameter:(id)params];
what could be in initWithParameter for adhere to memory rules ? And what if MyObject extends some other object ? I also find out that method naming rules are important to properly advise programmer, what are this rule ?
Also could you point out a web link where this is explained (I am not yet good in finding docs on apple web site).
thanks
This is the page you're looking for: Memory Management Rules. It all comes down to adhering to the rules of ownership for an object.
If you create an object using alloc then you own that object and must release it. For example:
NSString* str = [[NSString alloc] init];
//do something with your str object
[str release];
str = nil; //don't forget to set it to nil, it's still
//pointing to the (now unallocated) block of memory
If you create an object using a factory method, for example:
NSString* str = [NSString stringWithString:#"blah"];
Then what is happening here is that it is creating the string object using alloc for you and then returning the object but first adding it to the local autorelease pool. To use the example in your question.
return [[MyObject alloc] initWithParameter:(id)params]; // possible leak
return [[[MyObject alloc] initWithParameter:(id)params] autorelease]; //now autoreleased -- no leak
Here is the page on Autorelease Pools. Apple say it better than me.
An autorelease pool is an instance of NSAutoreleasePool that “contains” other objects that have received an autorelease message; when the autorelease pool is deallocated it sends a release message to each of those objects. An object can be put into an autorelease pool several times, and receives a release message for each time it was put into the pool. Thus, sending autorelease instead of release to an object extends the lifetime of that object at least until the pool itself is released (the object may survive longer if it is retained in the interim).
Method naming rules are important as it gives a strong indication as to whether the method returns an autoreleased object. In this example I would name the method:
[MyObject myObjectWithParameter:(id)param]
Hope this has helped.
It is standard practice for alloc and creation methods to return a retained object. Anything that starts with init, create, or the object name will clue other programmers into the purpose of the method.
Even if you create with alloc, if the purpose of your method is to pass on ownership, you should not release the object.

Some beginner Objective-C/iPhone questions

I'm just starting out (reading up a lot for the past couple of days). Here's some questions that I have stacked up, hopefully someone can answer them.
1. the (self != nil) check in initializer code. Why do it? To prevent accidental access to some "run-only-once" code that's wrapped up in there? Where from could this accidental access come from? Doing such checks suggest that I don't have control over what's going on.
- (id)init {
self = [super init]
if (self != nil) {
// Code..
}
return self;
}
2. How is it that you don't have to free up anything that static methods return? (or this is the idea I've got)
3. How is str = #"Hi there!" different from
str = [[NSString alloc] initWithString:#"Hi there!"];
As I understand, you have to release str in aquired with second method, but not with first? If so, when does the first one get released? Which one is preferable (not minding the typing length)?
4. What is autorelease, if iphone has no garbage collection? I've noticed something called "an autorelease pool" being created in main.m. Is [myObject autorelease]; a way of adding myObject to the nearest wrapping "autorelease pool", which will release it? Basically, some magic to avoid releasing it yourself? Why use it?
Well, thats it for now. Thanks for any answers!
In Objective-C, it's possible to return an instance other than self from -init. Classes do this, for example, to enforce a singleton instance, or in the case of class clusters. NSNumber, for example, returns a subclass depending on the type of value passed to its initializer. So when you call [[NSNumber alloc] initWithLong:long_value], NSNumber's -initWithLong: initializer is called after NSNumber's +alloc, but a subclass of NSNumber may be returned to the oringial caller. Thus the pattern
self = [super init];
which reassigns self to the value of [super init] so that self points to the actual instance that [super init] returned. If +alloc or the super's init method fails, the result of [super init] may be nil. To avoid, side effects in the case of a failed initialization, the pattern then becomes
- (id) init {
if(self = [super init]) {
// do initialization of instance variables etc.
}
return self;
}
Note that you must return self (or nil or an other instance) from the init method. You should assign self to [super init] and you may check for nil before doing more work.
You may have to release the return value of a staic method. You should read the Cocoa memory management guide. The rule is generally quite simple: If the method you call has "new", "alloc", or "copy" in its signature, the result belongs to the caller and the caller must call -release on that instance or there will be a memory leak. Of course you should call -retain on anything else (i.e. not from an "alloc","new" or "copy" method) you want to keep a reference to and then call -release or -autorelease when you are done with that instance.
str = #"Hi there!", assuming str was declared as NSString *str; assigns the address of the string constant #"Hi there!" to the value of thestrvariable. You do not need to retain or release string constants.str = [[NSString alloc] initWithString:#"Hi there!"];allocates a new string instance. The value ofstrwill be the address of this instance. Each call ofstr = [[NSString alloc] initWithString:#"Hi there!"];again will allocate a new instance. So afterstr2 = [[NSString alloc] initWithString:#"Hi there!"];,str != str2, while afterstr2 = #"Hi There!", str==str2. See this answer as well.
-autorelease adds the receiver to the current NSAutoreleasPool. When the pool is drained (usually at the end of the current run loop iteration, or when the pool is manually drained), the pool calls -release on all instances in the pool. If this -release drops the retain count to 0, the object is deallocated (and -dealloc called) just as with any other -release. Using an autorelease pool is generally frowned upon on the iPhone because it may cause you to accumulate many unused instances in the pool before it is drained at the end of the run loop iteration. If you can use -release instead of -autorelease, you generally should. Again, see the Cocoa memory management guide for more info.
There is a school of thought that in most cases, allocating the self pointer is something that the system should do, and not the programmer.
Also, many people prefer to keep the main line of program flow as un-indented as possible. In which case the initialisation code could be re-written as:
- (id)init {
if (![super init]) {
return nil; // There is a problem so bail early.
}
// Initialisation code here.
return self
}
Will Shipley explains this much better than I do.
1: This check is to ensure that the super constructor returned a new object.
2: Static methods don't refer to an instance
3:
str = #"Hi there!"
This assigns the address of the constant string "Hi there!" to the pointer str
str = [[NSString alloc] initWithString:#"Hi there!"];
This allocates a string and copies "Hi There!" to it. This means that a) str is modifiable and b) needs to be deallocated when you are done with it.
calling
self = [super init];
May return nil if the superclass cannot initialize itself for some reason or other, including memory being unavailable, or certain prerequisites have not been met. If that is the case, you don't want to be trying to set variables of self, or set self as a delegate, or add self to an array, if self is nil.
The autorelease pool is something created upon every event the iPhone sends your application. It is created before any code runs, and released after all your code is done, for each event. Any objects that you call autorelease on will be put into the current autorelease pool. Any objects in the autorelease pool will be released as many times as they were added, after your code completes. In this way, you don't have to worry about who's responsible for releasing an object created by one method and returned to another method.
You can create your own autorelease pools as necessary.
str = [[NSString alloc] initWithString:#"Hi there!"];
This line creates a string that is not in an autorelease pool, so you have to release it manually. Simply writing
#"Hi there!";
returns a string that you don't have to worry about releasing. Extending your previous example:
str = [[[NSString alloc] initWithString:#"Hi there!"] autorelease];
would be another method of creating a string you don't need to worry about releasing.
One difference between garbage collection and autorelease pools is that garbage collection works with circular references. Using autorelease pools, you don't want to have two objects that retain each other and hope that once nothing else refers to them, they will go out of existence; they won't.
If self is nil after the super initialisation then you're probably out of memory. Your only reasonable course of action is to return nil and hope things get handled gracefully further up the stack.
Static methods aren't allowed allocate on the heap, therefore there's nothing to free.
In the first instance, the string is compiled into the data segment of your app and cannot be freed. In the second instance, you are allocating memory from the heap and copying your static string (from the data segment) into it.
It's simple garbage collection. As to why to use it, the simple answer is don't. It's not recommended to use autorelease on the iPhone due to limited resources.