-[CFString intValue]: message sent to deallocated instance 0xa3a2610 - ios6.1

I find some same topic in stackoverflow, but i can't solve my problems.
This is my code
In my .h
#property (nonatomic, retain) NSMutableArray *favoriteShops;
My .m
NSString *idStr = #"";
NSString *shopTypeId = #"";
for (SHDFavoriteShopView *favoriteShopView in favoriteShops) {
idStr = [favoriteShopView valueForKey:kId];
shopTypeId = [favoriteShopView valueForKey:kShopTypeId];
if (tappedView.tag == [idStr intValue]) { // Crash here
shop.shopType = [shopTypeId intValue];
break;
}
}
I have problem sometime, not usually.
Could you please help me.
Thanks you

It's an indication that the string you are accessing (idString in this case) has already been freed. There are a number of reasons why this can happen. If the string was originally allocated via an auto-released method (such as [NSString stringWithFormat:#"..."]), and the string got auto-released. Or if you allocated the string, but later released it by explicitly calling [idStr release]. You need to make sure that you are not re-using a string after it's already been released. That can be tricky!

Related

Does Objective-C really set an uninitialized local object pointer to nil under ARC?

Recently I got a few EXC_BAD_ACCESS crashes from firebase when calling [NSString stringWithFormat:]. The code snipped is as follows:
#define TYPE_A #"typeA"
#define TYPE_B #"typeB"
- (void)myMethod {
NSString *type;
if (condition1) {
type = TYPE_A;
} else if (condition2) {
type = TYPE_B;
}
if (type) {
NSString *message = [NSString stringWithFormat:#"Message: %#", type];
}
}
This snippet is very simple so the only cause I can guess is that when type is declared, it is assigned a garbage value.
However, I found out that someone claimed years ago that under ARC, object pointers like this will be set to nil.(See Link1 Link2) If this is true, maybe there's a bug in LLVM; if not, what caused this crash?

NSString : leak when assigning value to a property

Assuming we don't use ARC.
Suppose we have a very simple class in which we declare 2 NSString properties, like this :
#interface Foo : UIView {}
-(id)initWithArguments:(NSString*)mess title:(NSString*)tit;
#property(nonatomic, retain) NSString *message;
#property(nonatomic, retain) NSString *title;
#end
and in implementation :
#implementation Foo
#synthesize message, title;
-(id)initWithArguments:(NSString*)mess title:(NSString*)tit{
if((self = [super init])){
message = mess; // (1)
self.title = tit; // (2)
(...)
}
return self;
}
-(void)dealloc{
message = nil;
title = nil;
[super dealloc];
}
#end
Now if I call a method from another class, in which I create 2 NSString and an instance of Foo , like this :
-(void)someMethod{
NSString *string1 = [NSString stringWithFormat:#"some text with %d things", 5];
NSString *string2 = [NSString stringWithFormat:#"other text with %d things", 5];
Foo *foo = [[Foo alloc] initWithArguments:string1 title:string2];
}
The whole code works fine and doesn't crash, but, if I profile it with instruments,
it doesn't cause a leak when calling (1)("message = mess;")
it cause a leak when calling (2)("self.title = tit;")
It's very confusing, because stringWithFormat is an autoreleased object, isn't it ?
So, how an autoreleased object can cause a leak when assigning to a property ???
I read somewhere that it's almost always better to use the "self.text = value;" form instead of the "text = value;" form, because the second one may cause a leak.
Actually, in this code it's the contrary.
And... If I use a constant NSString like #"some text", instead of the values returned by [NSString stringWithFormat], there is no leak, of course.
Any idea ?
You have forgotten to invoke the (compiler-generated) setter methods in a few cases:
self.message = mess; // in init method
self.message = nil; // in dealloc method
self.title = nil; // ditto
It's crucial that you use the setter/getter methods in non-ARC code.

Synthesized getter not working for instance variables of type NSString

Hi I'm a newbie in Objective-C programming. Today I was writing a program and I'm quite confused with the way it behaves. Here is the program :
#import <Foundation/Foundation.h>
#interface MyClass:NSObject
{
NSString * str;
}
#property NSString * str;
#end;
#implementation MyClass
#synthesize str;
#end
int main()
{ NSAutoreleasePool * pool = [[NSAutoreleasePool alloc]init];
MyClass * obj = [[MyClass alloc]init];
[obj setStr: #"hello"];
/* the following lines of code will give error if not commented but why it is
resulting in error ?????
NSLog(#"Str = %#",[obj getStr]); // **gives error if not commented**
**or**
NSString * temp;
temp = [obj getStr]; // gives error
NSLog(#"%#",temp);
*/
NSString * temp;
temp = obj.str;
NSLog(#"%#",temp); // works just fine
[pool drain];
return 0;
}
In main function when I try to print the str value using getStr a synthesized accessor it gives me error. Why so? Are we not allowed to use synthesized getter for NSString or am I not using the getter in a correct way?? But still the synthesized setter [obj setStr] sets the value for NSString type.
I saw some answers here and there for this kind of questions on stack overflow but I really din't understand the answer which were provided there so please explain this in a simple manner for me. Many thanks.
The name of the synthesized getter for property xyz is the same as the name of the property, i.e. xyz. It is not getXyz. Only the setter gets prefixed with a "set", becoming setXyz:
That is why your code
NSLog(#"Str = %#",[obj getStr]);
does not compile. Changing to
NSLog(#"Str = %#",[obj str]);
will fix the problem.
Note: when you let Xcode synthesize a property for you, a variable to "back" that property is also created. You do not need to declare an instance variable str in addition to the property str.
This is not getter method call temp = [obj getStr];. Getter method is trigger by either [obj str]) or dot notation obj.str. But you can define getStr, if you do, then use as you have done.
Another way to access getter and setter of a property:
//getter
NSLog(#"Str = %#",self.str);
//setter
self.str = #"hello";

Over-release an object and the app does not crash

#property (retain) NSString *testString;
self.testString = [[NSString alloc] initWithString:#"aaa"];
[self.testString retain];
self.testString = [NSString stringWithString:#"a"];
[self.testString release];
[self.testString release];
Let's go line by line:
Line 2: retain count of testString = 2
Line 3: retain count of testString = 3
Line 4: retain count of testString = 1
Line 5: retain count of testString = 0
Line 6: it should crash
Even if there's other stuff holding to testString in CoreFoundation, it eventually will go away. But the app never crash due to this.
Anyone could explain this? Thanks!
see this code and its log:
NSString *string1 = [NSString stringWithString:#"a"];
NSString *string2= #"a";
NSLog(#"String1: %p", string1);
NSLog(#"String2: %p", string2);
2012-03-22 13:21:49.433 TableDemo[37385:f803] String1: 0x5860
2012-03-22 13:21:49.434 TableDemo[37385:f803] String2: 0x5860
as you see [NSString stringWithString:#"a"]; doesn't create a new string, it uses the string literal #"a". And string literals can't be deallocated.
Try your code with NSMutableString and you will see a crash.
I am not an expert about this, so please take this with a grain of salt. I guess that [NSString stringWithString:#"a"] will probably just return the literal string #"a", i.e. it just returns its argument. As #"a" is a literal, it probably resides in constant memory and can't be deallocated (so it should be initialized with a very high retain count).
[NSString stringWithString:#"a"] returns an autoreleased object. That means "the true" retain count is 2 not 1 in line 4. In line 6 you are overreleasing your variable but the crash will happen later - on the autorelease pool drain.

How to release a string created inside a method?

I have declared a local string inside the method. I am releasing the string inside the same method. I found my code crashing if release that object. If I don't release the string, code runs successfully.
I have called that method in viewdidappear so that method is called while pushing and poping. Nothing gets printed in the console. Here is my code
-(void)appendString{
NSString *locStr = [[NSString alloc] initWithString:#""];
for (int i=0;i<[result count]; i++)
{
locStr=[locStr stringByAppendingFormat:#"%#",[result objectAtIndex:i]];
}
[str setString:locStr];
[locStr release];
}
I am calling the "appendString" method from "viewDidAppear"."str" is a NSMutable string declared in .h class.How should I release the "locStr".
What went wrong in my code? This isn't the normal way to release it?
Try this:
-(void)appendString{
//stringWithString returns an autorelease object
//so you don't need to worry about its memory management
NSString *locStr = [NSString stringWithString:#""];
for (int i=0;i<[result count]; i++)
{
//if your locstr is created by initWithString instead,
//the following line is going to cause memory leak
locStr=[locStr stringByAppendingFormat:#"%#",[result objectAtIndex:i]];
}
[str setString:locStr];
//[locStr release];
}
And make sure that the string property in your str instance is set to retain
You may want to use NSMutableString and not create multiple string objects that may or may not release at some time in the distant future.
-(void)appendString
{
NSMutableString *locStr = [[NSMutableString alloc] initWithString:#""];
for (int i=0;i<[result count]; i++)
{
[locStr appendFormat:#"%#",[result objectAtIndex:i]];
}
[str setString:locStr];
[locStr release];
}
see
In your code, calling [locStr release] is sent to the NSString instance returned from [locStr stringByAppendingFormat:#"%#",[result objectAtIndex:i]] That code actually returns a new String instance, so your variable locStr is now pointing to that new NSString instance and your reference to the original one is lost.
So it is NOT the instance of the NSString you created with [[NSString alloc] initWithString:#""]
The NSString returned from stringByAppendingFormat is autoreleased and your [locStr release] would over-release it. As the other answers indicate you could just use a NSMutableString to avoid lots of NSString instances to be created in your loop and actually releasing the original created instance.
No need to alloc/init locStr. This should do the trick:
-(void)appendString{
NSString *locStr = #"";
for (int i=0;i<[result count]; i++) {
locStr=[locStr stringByAppendingFormat:#"%#",[result objectAtIndex:i]];
}
[str setString:locStr];
}
Don't release, use autorelease. This is the way if you need to return something. When there is an autorelease pool (which is in most cases) it is released automatically. That's what methods like stringByAppendingFormat do also.
Or wait, when you di something like this, it is important, that you retain the Object in the setter Method. It is better then to use a property like
{
NSString* thestring;
}
#property (nonatomic, retain) NSString* thestring;
and a
#synthesize thestring;
in the .m file.
use this
locStr=[[locStr stringByAppendingFormat:#"%#",[result objectAtIndex:i]] retain];
then you can release this same as you are doing.
what happens here you get an autorelease object of string by stringByAppendingFormat method.
so you need to convert it into a retain copy.

Resources