i wrote this code :
bs = [NSNumber numberWithFloat:[mystring.text floatValue]];
NSLog(#"bs = %#",bs);
....
float x = [bs floatValue];
when the program want to excute the line above it crash why ?
the output :
bs = 2.8 which true 100%
Between the time you assigned an NSNumber object to your ivar bs it was release by the runtime. I am assuming where you created bs and where you try to assign it to x are in two different methods. If that is the case, you need to tell the runtime you want to keep the ivar bs around for awhile:
[bs retain];
And if you do that, you need to tell the runtime you are done in the dealloc:
-(void)dealloc {
[bs release];
[super dealloc];
}
Basically, if you didn't create an object with alloc, copy, mutableCopy, new in the method name, then you don't own the object.
the code snippet seems ok.
and I guess the reason is bs was released before fetching its float value.
the simplest way to retain bs is to change it to a property:
#property (nonatomic,retain)NSNumber* bs;
and release it in dealloc
Related
I have a lot of objects named _Obj_1, _Obj_2, etc...
And I want to release all.
I'm using KVC. In particular to release all, i use:
MyClass *obj = nil;
for ( int i=1 ; i<=14; i++ ) {
obj = [self valueForKeyPath:[NSString stringWithFormat:#"_Obj_%d", i]];
[obj release];
}
clang analyzer tell me for [obj release];
Incorrect decrement of the reference count of an object that is not
owned at this point by the caller?
How can I fix it?
It's not an ARC project.
This can be fixed very easily
If you don't own the object (you didn't call retain), don't release it!
Instead of having lots of variables with the same name, use an array to hold the objects. Then the releasing will be only the release of an array.
I need to call a function after a CCSpeed delay so that I can change the speed dynamically. As far as I know, I can't use a CCSpeed inside a CCSequence, so I tried using a CCSequence (CCDelayTime, CCCallFuncND, nil) inside a CCSpeed, which also doesn't appear to work. Anyone have any suggestions?
In my BackgroundLayer class, I have a NSNumber *multiplierSpeed; :
#interface BackgroundLayer : CCLayer {
NSNumber *multiplierSpeed;
}
#property (nonatomic, retain) NSNumber *multiplierSpeed;
-(void)rotateWorldAndSwapIn:(id)sender data:(int)frame;
#end
And in my implementation:
#synthesize multiplierSpeed;
-(id)init {
self = [super init];
if (self != nil) {
//...
multiplierSpeed = [NSNumber numberWithFloat:1.0f];
CCSpeed *delay = [CCSpeed actionWithAction:[CCSequence actions:[CCDelayTime actionWithDuration:20],[CCCallFuncND actionWithTarget:self selector:#selector(rotateWorldAndSwapIn:data:) data:(void*)3], nil] speed:1.0f];
[delay setTag:10];
[self runAction:delay];
//...
}
}
-(void)rotateWorldAndSwapIn:(id)sender data:(int)frame {
CCLOG(#"test"); //This is fine
CCLOG(#"multiplierSpeed=%f",[multiplierSpeed floatValue]); //Crashes here
//...
}
I am getting this error:
EXC_BAD_ACCESS on callbackMethod_(targetCallback_,selector_,target_, data_);
in the CCActionInstant.m file.
Also, is it because CCSpeed wraps around CCCallFuncND, which has no delay, that's throwing this error? If so, do you have any alternative suggestions?
Thanks for helping!
You need to use self.multiplierSpeed instead of only multiplierSpeed.
self.multiplierSpeed = [NSNumber numberWithFloat:1.0f];
and then in the CCLOG,
CCLOG(#"multiplierSpeed=%f",[self.multiplierSpeed floatValue]); //Won't crash anymore
Unless you use self.varName, Objective-c won't be using the getter/setter methods, rather would try to access the instance variable directly causing a bad memory access (as no memory was allocated for that var)
It's crashing because this:
multiplierSpeed = [NSNumber numberWithFloat:1.0f];
...isn't retained in your init. By the time you get to the action callback, that object has been released and is invalid. There's probably no good reason to store that value in an NSNumber anyway. Set up your iVar as a CGFloat and then you can store and access the multiplier without worrying about retains. If you really need that as an NSNumber, you'll need to retain it in init (or through a property) and then release it when appropriate, at least in your dealloc.
I have a setter like this:
- (UIImagePickerController *) foto {
if (_foto == nil) {
_foto = [[UIImagePickerController alloc] init];
_foto.delegate = self;
}
return _foto;
}
it is declared like
#property (nonatomic, retain) UIImagePickerController *foto;
with
#synthesize foto = _foto;
on my dealloc I have
[_foto release];
At some point in my code I want to do this
self.foto = nil;
but something in my soul says the object assigned to self.foto previously will leak, because it was alloc on the setter... how do I make it right?
thanks.
Edit: No, that should be fine. As long as you don't assign something else to _foto before you release, it should work.
Yup. You create an object, then loose the pointer to it. If you throw an autorelease on the init line, that will fix it. You could also use ARC.
The init line doesn't actually do anything... You assign the pointer to an object you create, then assign it to something else.
I don't think there is a leak there. When you assign to self.foto like this:self.foto = nil;, it will release the former one automatically. If you assign it by this way: _foto = nil;, you need to release it manually before the assignment.
Yes that works, and will not leak. When you set the value of _foto, its retain count is 1 (because you called alloc). As long as you release it (which you've said you do) in dealloc, you should be fine, as the retain count will go back to 0. UNLESS your setter is ALSO written by you, and written improperly. It needs to explicitly release the old value, if it's not nil. Something like this:
- (void)setFoto:(UIImagePickerController*)foto {
if (_foto) {
[_foto release];
_foto = nil;
}
if (foto)
_foto = [foto retain];
}
.h
# interface MyClass : NSObject {
UILabel *mTextLabel;
}
#property (nonatomic, retain) UILabel *mTextLabel;
and Declare #synthesize mTextLabel in the MyClass.m;
and release the object like this.
[self setMTextLabel:nil];
[mTextLabel release];
NSLog (#"%d",[mTextLabel retainCount]);
This result is 0. and I have not found any error or interrupt.
But. When I release mTextLabel like this. I have just got EXC_BAD_ACCESS
[mTextLabel release];
[self setMTextLabel:nil];
I don't understand why it happen. Plz help me.
When you have a synthesized property with the retain attribute, the synthesized setter calls release on the old ivar before it sets the new value.
Here is an expanded view of what is happening in the first example:
[mTextLabel release];
mTextLabel = nil;
[mTextLabel release];
Since calling a method on a nil pointer does nothing, there is no problem.
In the second example, here is what is happening:
[mTextLabel release];
[mTextLabel release];
mTextLabel = nil;
See the problem?
Edit: it is also worth noting that inspecting the retain count of an object is rarely useful, as any number of Cocoa classes may retain it for their own purposes. You just need to be sure that every time you call retain, alloc, copy or new on an object, there is a matching release or autorelease somewhere in your code.
The problem is you are calling release then you are setting the property to nil which also sends a release to mTextLabel before setting it to nil. This is what happens when the property is defined as copy or retain. All you need is the following code.
[mTextLabel release];
mTextLabel = nil;
Edit:
I would like to add that in your code outside of init and dealloc it is completely fine to call self.mTextLabel = nil to properly release if necessary and nil the value of the property. It is however recommended to NOT use the property in the init/dealloc calls. In those cases you will want to create / release the objects directly to avoid the side effects of the accessor.
The value is already released when you do [self setMTextLabel:nil]. You don't need to release the value explicitly (unless you created the value using an init or copy method, in which case you should release it as soon as you've assigned to self.mTextLabel).
Note that retainCount has a return type of NSUInteger, so cannot ever be negative. So checking to make sure the retain count is zero and not -1 doesn't work.
for a day now I stare at the following routine and can't get my grips around it. I have a class such as:
MyClass.h
...
#interface MyClass : NSObject {
NSNumber *myNumber1;
NSNumber *myNumber2;
}
#property (nonatomic, retain) NSNumber *myNumber1;
#property (nonatomic, retain) NSNumber *myNumber2;
#end
and the m-file
#import "MyClass.h"
#synthesize myNumber1, myNumber2;
#implementation MyClass
-(id) init {
self = [super init];
NSLog(#"Retain Counts myNumber1: %d, myNumber2: %d", [myNumber1 retainCount], [myNumber2 retainCount]);
myNumber1 = [NSNumber inbitWithint:10];
myNumber2 = [NSNumber inbitWithint:2];
NSLog(#"Retain Counts myNumber1: %d, myNumber2: %d", [myNumber1 retainCount], [myNumber2 retainCount]);
return self;
}
...
I use this class as a globals container and instantiate it from every other class in my app using a
MyClass *myGlobals = [[MyClass alloc] init];
===>>> the weirdo >>>
Running the routine I have the following facinating console output:
Retain Counts (before) - myNumber1: 0, myNumber2: 0
Retain Counts (after) - myNumber1: 1, myNumber2: 26
How can that be?
Do not call `retainCount`
The return value of retainCount can only be considered accurate if you are calling it on an instance of a class you wrote and you have never ever not even once passed said instance to any API provided by the system.
The absolute retain count is an implementation detail for which you might not have any control.
Assuming, for the moment, that your code was typed and, thus, the errors are not really in your original code...
NSNumber caches a subset of common values. That is, for some numeric values, there is a single instance of NSNumber that is returned for all requests to retrieve an NSNumber instance wrapping that number.
If this is your actual code, it shouldn't work at all, it should simply crash. If not, you should cut and paste your actual code.
However, a couple of things.
First, if you use an NSNumber as an ivar, like anything else, you must take ownership of it. If you plan to use a convenience constructor, you must either assign it using the property on self, or send it an explicit retain message.
Second, you typed something like initWithInt: here. If you are actually using that message, then you have never actually allocated the number in the first place. You must replace this with one of the following:
myNumber1 = [[NSNumber alloc] initWithInt:10]; // explicitly create the number
myNumber1 = [[NSNumber numberWithInt:10] retain]; // take ownership through retain
[self setMyNumber1:[NSNumber numberWithInt:10]]; // use the property accessors to deal with ownership and the convenience constructor to create the number
However you choose to do it, you must at some point take ownership of the object.
You should never even look at retainCount as it carries little significance anyway. The reason you see the count of 26 is that probably somewhere in the frameworks (or even in your own app) other instances of NSNumber exist that are created with the same int 2. An NSNumber is immutable, and so as an optimization NSNumber probably just gives you back an instance it has created earlier. As long as you don't look at retainCount it doesn't matter to you.