Strange BAD_ACCESS when printing NSInteger - objective-c

this is my first time asking something here, so don't be too harsh on me please :-). I have a strange "bad access" issue. In a class of mine I have a NSInteger along with a few other members. I override the - (NSString *)description method to print the values of everything like so (omitted the unrelevant part):
- (NSString *)description {
return [NSString stringWithFormat:#"Duration:%d", duration];
}
and then I print that using NSLog(#"%#", myObject) which is giving me EXC_BAD_ACCESS without any log messages, regardless of the NSZombieEnabled.
I have double checked the order of all formatting specifiers and
parameters - it's correct.
I tried changing the format specifier to %i and %# and didn't get any result
When I init my object I don't initialize
duration. Later, I assign it through a property #property NSInteger
duration. So I tried initializing the duration to 0 in my init
method but to no avail.
If I box duration to a NSNumber prior to
printing, it works.
When I remove the duration and leave all the
other ivars it works again.
I'm stumped, what am I doing wrong here?
Can you help me?
Thanks a lot!
EDIT: To summarize, It seems this is caused by differences between 32 and 64 bit platforms, because it's fine when run on an iphone 4 and has issues only when run in the simulator. I tried 3 different approaches - using %d and %i with the NSInteger variable itself, using %qi and using %ld/ %lx and I also tried to cast to int and long with the various format specifiers. Every time I can run on the device, but get EXC_BAD_ACCESS in the simulator.

The only guess here: NSInteger could be 64 bit in your case and %i (as well as %d) expects 32-bit integer, you can try %qi or (what seems to be better) cast the value explicitly.

When you run the app in the debugger, where exactly is the signal raised? Xcode will show you the precise line and stack of the problem.
When you are sure the crash happens in the stringWithFormat: method it's probably a matter of format specifiers. Apple's String Programming Guide contains information on how to handle NSInteger in a safe and platform independent way.

Maybe you need to synthesyse your property?

Related

Logging a NSUInteger breaks xcode [duplicate]

This question already has answers here:
"Thread 1: stopped at breakpoint" error when initializing an NSURL object
(3 answers)
Closed 8 years ago.
I'm doing a tutorial on codeschool http://tryobjectivec.codeschool.com/ and according to this tutorial the following code should work:
void (^sumNumbers)(NSUInteger, NSUInteger) = ^(NSUInteger num1, NSUInteger num2){
NSLog(#"The sum of the numbers is %lu", num1 + num2);
};
Well, I tried the let this work, allthough xcode already gave me some orange error message:
I tried to build the code anyway, just to see if xcode was right or the tutorial was right. Well, something broke:
But even worse, I can't get xcode fixed again, xcode now pretends that all my code that I've ever wrote is causing problems. But I'm pretty sure it used to work:
NSUInteger is, at least in a 32-bit architecture, typedefed as an unsigned int, not a long. The %lu formatter specifies that you want to print them as longs, so there's a type conflict. If you print them as %ud, which is an unsigned int.
The blue marker in the gutter of the line sumNumbers(10,20); indicates that you have a breakpoint set on that line, which causes the interruption of the app. Remove/disable that breakpoint and that will work fine as well.
It is generally advised that you do not use NSInteger, NSUInteger, CGFloat, or CFIndex as direct parameters to an NSLog, or any other operation using a printf-style formatter. The reason is that their size varies between 32 and 64 bit architectures.
In your case, the correct way to write the code is to cast the NSUInteger to an unsigned long which is 64 bits on both architectures, at least as far as the XCode toolchain is concerned. Be warned that this may not be the case on other systems - for example, the C++ standard only requires that a long be at least 32 bits in size.
void (^sumNumbers)(NSUInteger, NSUInteger) = ^(NSUInteger num1, NSUInteger num2){
NSLog(#"The sum of the numbers is %lu", (unsigned long)(num1 + num2));
};
With regard to the tutorial, the person who wrote it was probably working on a 64 bit system, so NSUInteger mapped to the size required by %lu. Everything you read on the Web, from Apple documentation to Stack Overflow answers will have errors somewhere.
In order to NSLog your NSUInteger, you should change your statement to this:
NSLog(#"%ud", num1 + num2);
The reason your app is not running properly anymore is probably because you still have your breakpoint set. Go to Debug > Deactivate Breakpoints or use the shortcut ⌘Y, and then try running your application.

Can't find the source of this "Expected Identifier" error, any thoughts?

I'm very new to Objective-C and programming in general and I'm having some difficulty solving a strange error I'm getting in my code. I've rechecked my code line-by-line but no matter what I do I get an "Expected Identifier" error on this one line.
NSString *text = [NSString stringWithFormat:#"Your total is $%.2f", [self.cartTotal]];
I've retyped the line several times to make sure that I wasn't missing any typos, but a little red arrow is pointing to the first closing bracket.
Take [self.cartTotal] out of the brackets. They're unnecessary here.
Should be:
NSString *text = [NSString stringWithFormat:#"Your total is $%.2f", self.cartTotal];
To help understand the error (assuming you're coming from a language like Java or C++), what you've written is the equivalent to writing this in say Java:
this.cartTotal.
Notice the hanging dot at the end? That's what you've done here basically. In Java, that dot suggests you're calling a method on whatever object cartTotal is, or access a public variable on that object. I'm not sure what a Java or C++ error message would say here, but this is the equivalent scenario.
Given #GregParker's excellent comment...
You created cartTotal by way of a #property.
#property double cartTotal; // or something like this
This creates three things:
A setter
A getter
An instance variable
The setter is accessed in two ways:
[self setCartTotal:value];
Or:
self.cartTotal = value;
These both do the same thing.
The getter is likewise accessed in two ways:
[self cartTotal];
Or:
self.cartTotal;

Issue with NSLog when printing BOOL type

(XCode 4.3)
Why does the following crash at the NSLog statement with EXC_BAD_ACCESS?
BOOL autoFlag
#property BOOL autoFlag
#synthesize autoFlag
[object setAutoFlag:YES]
NSLog(#"%#", [object autoFlag]); //crashes here in debugger with EXC_BAD_ACCESS
I managed to get around it with NSLog(#"%d"..., which prints 1, but why doesn't #"%#" work? I thought it just converts the value to a string?
%# is used to print the description of objects that are descendants of the NSObject class, this however can be overwritten to make your objects print whatever you want.
Unless autoFlag is an object it will crash your program. It is very common to get these type of errors in NSLog Statements since the compiler cant tell what kind of "thing" you want to print and most of the time it wont be able to know before hand (there are some exceptions in where it will tell you that you are using the wrong identifier).
If what you want to see is something like "True" or "YES" then you need something like
NSLog(#"Auto Flag: %#",object.autoFlag? #"True":#"False");
Take a look at: https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/Strings/Articles/formatSpecifiers.html
%d works because you are telling it to print your boolean value as an integer, so you will get back either 0 (false) or 1 (true) using this method. There is no specific formatter for a boolean.
You encountered a crash because the code is expecting a pointer to a memory address by using %#, and instead you gave it a primitive datatype, in this case a boolean. When the application tried to use this address and there was no object there, you got a EXEC_BAD_ACCESS.

Comparing NSNumber value with defined int

I'm trying to store a constant int value to compare against in a particular scenario. My define looks like this:
#define kApiSuccessCode 0
And I have a method which compares a statuscode (NSNumber) with this to give a BOOL result:
- (BOOL)isSuccess {
return [self.statusCode isEqualToNumber:[NSNumber numberWithInt:kApiSuccessCode]];
}
I have a synthesized NSNumber property like this:
#property (nonatomic, strong) NSNumber *statusCode;
The problem is I get a Execution was interrupted, reason: EXC_BAD_ACCESS error when running this code - I can't work out why? Is this a bad way to compare int values? Thanks
SOLVED:
Turns out I was making the basic mistake of trying to NSLog a BOOL value i.e NSLog(#"Does this work? %#", [response isSuccess]). So the code itself works - but THANK YOU to everyone for your suggestions for making this more efficient!
I don't know why the crash is occurring, but to answer your other question, yes, this is not a great way to compare int values.
There are valid reasons to store values in NSNumber instances, but in most cases it is overkill. If you do, in fact, have an NSNumber instance, just use intValue to get it's integer value and compare it to a primitive instead of creating a whole new instance.
If you look at Foundation classes, you'll see most of the time, they rely on NSInteger primitive types instead of NSNumber instances. For example, the NSURLResponse class uses an NSInteger to return the HTTP status code.
I would enable Zombies as instructed in this post.
It will then tell you if you are sending the message to a deallocated instance of the variable.
Once you figure this out, I would then suggest this instead:
- (BOOL)isSuccess {
return [self.statusCode intValue] == kApiSuccessCode;
}
Advantage and disadvantages of #define vs. constants?
As mentioned by others, #define doesn't have a type associated with it
=> kApiSuccessCode is not an integer, the pre-compiler just replace it with 0 before you program is compiled.

Xcode. Question about syntax error checking

Xcode looked at this line and did not complain. Project built, code crashed at runtime.
NSString *randomName = [NSString stringWithFormat:#"%#, %#, %#",
[randomAjectiveList objectAtIndex:ajectiveIndex],
[randomNounList objectAtIndex:nounIndex]];
Naturally, come to think about it, i have one too many "%#" in place, one more then actual arguments. Correct code should look as follows
NSString *randomName = [NSString stringWithFormat:#"%#, %#",
[randomAjectiveList objectAtIndex:ajectiveIndex],
[randomNounList objectAtIndex:nounIndex]];
I ask you though ... why didn't Xcode complain? Seems like such an obvious thing to do with param counters. Shouldn't this be checked at compile time? Is it specific to "%#", perhaps?
Please advise.
Based on a quick check, you're 100% right that this isn't checked at compile time, seemingly even by the static analyser. Conversely, NSLog is checked. So on my machine, with XCode 4.0.2, the following:
[NSString stringWithFormat:#"%d %# %#"];
NSLog(#"%d %# %#");
Produces a warning on the NSLog of "More '%' conversions than data arguments" but fails to comment on the NSString.
So, the difference could be fixed function calls versus dynamic calls. The compiler can't actually be completely certain where the NSString call will go because it's possible you'll have declared a category or used the low-level runtime to adjust the NSString selector table at runtime.
However, especially given the problems you'll almost immediately encounter if you start modifying the behaviour of the Foundation classes, like you I'd have expected at least a warning.