Objective-C EXC_BAD_ACCESS on run - objective-c

I'm creating a basic command line application using this tutorial: http://www.raywenderlich.com/40293/learn-to-code-ios-apps-2-strings-arrays-objects-and-classes
I'm at the stage where it is asks me to type in:
NSLog(#"You entered the word '%#' and it is %li characters long", inputString, [inputString length]);
When I do that, run the app and type in a word in the console window it says I should get
Please enter a word.
objects
You entered the word 'objects' and it is 7 characters long
Which does happen, but then the screen automatically switches to:
the error on the green bar says:
Thread 1: EXC_BAD_ACCESS (code=13, address=0x0)
Can someone explain this?

Run the Zombies instrument in Instruments. The crash is caused by releasing an invalid "object". Probably this is because the object was over-released. The Zombies instrument will tell you more about over-release problems.

There's nothing wrong with that line of code.
What's likely happening is that you have nothing after that line of code, and those lines you typed in need to live between the brackets in this template:
#import <Foundation/Foundation.h>
int main(int argc, const char * argv[])
{
#autoreleasepool {
// your code goes HERE
}
return 0;
}

Related

NSString gets corrupted, changes to NSPrincipalClass

I have an NSDragOperation that gets a property lists path upon the user dragging it into the window. That seems to work just fine, and I can save the path information to an NSString:
NString *thisPath = draggedFilePath;
NSLog(#" %#",thisPath);
output: 2014-02-09 09:19:46.072 app[5944:303] /Users/Me/Desktop/file.plist
The problem starts when I go into a dispatch queue. When I try and read the NSString from inside the background queue the output becomes NSPrincipalClass. Does anyone know why this is happening, or if I'm supposed to convert the NSString to some other format before entering dispatch_queue_t?
dispatch_queue_t backgroundQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async(backgroundQueue, ^{
for (NSUInteger i = 0; i < 1; i++) {
dispatch_async(dispatch_get_main_queue(), ^{
});
}
NSLog(#" %#",thisPath);
output: 2014-02-09 09:19:56.234 app[5944:12203] NSPrincipalClass
EDIT: the output of the string using NSLog inside dispatch queue turns up random symbols, and also crashes. The last output was <__NSMallocBlock__: 0x55a860> - I have other strings that seem to be just fine within the same function, so I really don't know what is causing this.
one of three things is happening...
it is being deallocated, and a new object is being allocated in its place... you can try zombies...
it is getting assigned to a garbage value ie. draggedFilePath isn't ever initialized to zero, and isn't set to a good value.
your stack is getting smashed and it just happens to be there when it crashes... this is the hardest to find.
you are going to have to turn on zombies, the exception breakpoint and just step through it in the debugger... if that fails you get to either run in instruments with the malloc tool or turn on malloc history logging.
Does it work if you prefix the declaration of thisPath with `__block'? Like this:
__block NString *thisPath = draggedFilePath;

Avoid crash report when a code snippet in CodeRunner throws exception

When using CodeRunner to test Objective-C code snippets, any exception thrown during run time will cause a crash, followed by the <my program> quit unexpectedly alert with complete stack trace and crash report saved in ~/Library/Logs/DiagnosticReports.
The exception can for instance be the result of a misspelled method name, and can happen quite often, depending on your personal development style. It is worth noticing that this crash report is also sent to Apple, which can seem a bit excessive for a misspelled method name.
Can this alert and crash report be avoided?
The default code template can be changed for each programming language in the app's Preferences settings.
If a try-catch block is added, the snippet can catch all its own exceptions and for instance just print out a log statement, hence avoiding the crash report.
For Objective-C, it can look like this:
#import <Foundation/Foundation.h>
int main(int argc, char *argv[]) {
#autoreleasepool {
#try {
%#
} #catch (NSException *e) {
NSLog(#"Exception caught: %#", e);
}
}
}
The %# defines the initial insertion point when a new file is opened.

NSZombiEnabled settings

I am trying to check NSZombieEnabled is working in my code.
I've the following settings :
and I've the following code in didFinishLaunchingWithOptions
NSString *string = nil;
[string release];
string = #"abc";
but, there is no error generated. there is no notification from NSZombie as well. Should I do some more settings. Please help me, cause I've a lib that I've imported and there is a EXC_BAD_ACCESS with code 13 happening, and I am not able to get to the error cause.
The stack and the console looks like this
Your settings are correct, but your code does not create any zombies. A zombie is an object which has been freed, but is re-used. Something like this will create a zombie:
NSString* string = [NSString stringWithString:#"abc"];
[string release];
[string length];
In this example, the string is released, and then you attempt to use it by calling its length method.
In the case of your library, what does the stack look like when it gives you the EXC_BAD_ACCESS?

NSAutoreleasePool is unavailable

I am following "Programming in Objective-C" 3rd edition and I am having problems with the first example.
I keep getting this error:
Semantic Issue: 'NSAutoreleasePool' is unavailable: not available in
automatic reference counting mode
Here is my code:
//
// main.m
// prog1 //
// Created by Steve Kochan on 1/30/11.
// Copyright 2011 ClassroomM, Inc.. All rights reserved. //
#import <Foundation/Foundation.h>
int main (int argc, const char * argv[]) {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
NSLog (#"Programming is fun!");
[pool drain];
return 0;
}
Any insight will be greatly appreciated.
The compiler is being asked to compile the file with ARC (automatic reference counting) enabled. Turn that off or, better yet, modernize your example:
int main (int argc, const char * argv[]) {
#autoreleasepool {
NSLog (#"Programming is fun!");
}
return 0;
}
(No, I can't tell you how, specifically, to turn off ARC, if that was the route you were to go down due to the aforementioned NDA.)
Quick post just in case you still looking
You can disable ARC in build settings.
Click on you project, in the left hand organizer.
Select your target, in the next column over.
Select the Build Settings tab at the top.
Scroll down to "Objective-C Automatic Reference Counting" (it may be
listed as "CLANG_ENABLE_OBJC_ARC" under the User-Defined settings
group), (if you do not find ARC option under build settings, you might need
to toggle you compiler. You can find it under build settings)
and set it to NO.
In my case, I wanted ARC on, and wanted to update a sample project to work properly. Apple's NSAutoReleasePool docs are technically correct, but don't come straight out and explain this. Here's how:
Take your application main, which probably looks something like this:
int main(int argc, char *argv[])
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
int retVal = UIApplicationMain(argc, argv, nil, NSStringFromClass([DemoAppDelegate class]));
[pool release];
return retVal;
}
And change it to look like this:
int main(int argc, char *argv[])
{
#autoreleasepool {
return UIApplicationMain(argc, argv, nil, NSStringFromClass([DemoAppDelegate class]));
}
}
Here is a link to Apple's transition guide to ARC.
OK...check this out. Specific change to NSAutoreleasePool - this is how Xcode initializes itself when you create your first app. I don't know about you, but I love this idea!
No worries if you are following along w/ Kochan's book. When starting your project, just uncheck the "Use ARC" box. Everything will work.
ARC is enabled when you first create a new project. Right know the only way I know how to enable or not enable it is when you first create your program. It is one of the checkboxes you have to unselect.

Why doesn't an iPhone app's main() function ever get a chance to finish?

Consider the following main() method which you would find most iPhone applications:
int main(int argc, char *argv[])
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
int retVal = UIApplicationMain(argc, argv, nil, nil);
[pool release];
return retVal;
}
In every iPhone app that I've run in Simulator with these (including several sample projects provided by Apple), the thread never exits UIApplicationMain() and any remaining code in main() is never executed. Is this expected behavior?
I have verified that statements after UIApplicationMain() never run by stepping through the code with a debugger. When the user stops an application (by hitting the "Home" button, for example), the resulting stack trace shows that [UIApplication _terminateWithStatus:] is eventually called. This function calls your application delegate's applicationWillTerminate: method. Once that finishes, [UIApplication _terminateWithStatus:] seems to kill/exit the thread.
Can someone confirm that this is how main() is supposed to work, or at least confirm the same behavior on their machine?
The original question was: "Why doesn’t an iPhone app’s main() function ever get a chance to finish?"
Short Answer: Because UIApplicationMain() is coded such that it never returns.
After doing several tests in Simulator and on the device, and asking another developer to do the same tests, I have confirmed that UIApplicationMain never returns. When the user terminates an application normally by hitting the Home button, The program ultimately terminates inside an unpublished UIApplication method called _terminateWithStatus. This method calls exit(0).
This behavior matches that of the NSApplicationMain function (which is AppKit/Cocoa version of the UIApplicationMain function). The documentation for NSApplicationMain() clearly states that it will never return.
I have submitted a bug (6600198) to Apple requesting that the official documentation (and Xcode template for main.m) be corrected to state that UIApplicationMain() never returns. While this is not a functional problem, the current template and docs are misleading.
Thanks to everyone for all the input and brainstorming!
Try:
int main(int argc, char *argv[])
{
NSLog(#"Step 0");
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSLog(#"Step 1");
int retVal = UIApplicationMain(argc, argv, nil, nil);
NSLog(#"Step 2");
[pool release];
NSLog(#"Step 3");
return retVal;
}
It may be that the release of the pool is preventing further logging in which case you'd get step 2 but not step 3.
If step 2 isn't being printed, then it's almost certainly something wrong with UIApplicationMain - there's a chance that it doesn't return so put NSLog statements (step 1.1, Step 1.2, ...) at various points within it and run to find the last message logged.
Keep drilling down (Step 1.7.1, 1.7.2, .... 1.7.6.3.2, ...) - eventually, you'll track down the exact line (however deep in the call hierarchy) when the log messages stop being logged and that line will be your culprit (either "turning off" logging or exiting without returning normally).
One further snippet I found on the web:
=====
When you use this line:
int retVal = UIApplicationMain(argc, argv, #"MyApp", #"MyApp");
The first MyApp is your main app delegate class. The second is the class to where SpringBoard sends touch notifications.
Also, if you are using the SDK, and have a main nib defined in the Info.plist, then you can leave the call as:
int retVal = UIApplicationMain(argc, argv, nil, nil);
as all that will be covered when you create your xibs.
=====
Now I don't know enough about iPhone development (specifically xibs) to know what that last bit even means (or if you've set it up correctly) but it sounds like another phase of compilation.
However, my first thought from reading that is that Springboard will call your delegate class when the buttons are pressed to ask you to do something (like shut down gracefully). If it can't ask you (i.e., no delegate), it's probably within its rights to shut you down as it sees fit, such as with [UIApplication _terminateWithStatus:].
In the Windows world, you would probably send off a quit message to the main window but, as I say, iPhone development may be different.
Still, it's an avenue to investigate. I'd be interested in seeing what calls were made to a delegate if you provided one. The code included with the snippet above had this:
#implementation MyApp
- (void) applicationDidFinishLaunching:(id)unused {
rect = [ UIHardware fullScreenApplicationContentRect ];
rect.origin.x = 0.0f;
rect.origin.y = 0.0f;
window = [ [ UIWindow alloc ] initWithContentRect: rect ];
[ window makeKeyAndVisible ];
view = [ [ MyAppView alloc ] initWithFrame: rect ];
[ window setContentView: view ];
}
- (void) dealloc {
[ window release ];
[ view release ];
[ super dealloc ];
}
So maybe a delegate with dealloc() is the secret to getting it to exit back to main(). Why don't you give that a shot? It may get you closer to your goal even if it doesn't solve the core problem.
After [pool release] there is nothing to log to?
trying using fprintf and see what happens
int main(int argc, char *argv[])
{
/*
...
same as above
...
*/
[pool release];
char file_name = "/tmp/log"
FILE *file = fopen(file_name, "w");
fprintf(file_name, "END\n");
}
and tell us what happens
I also thought the easiest way to check was to set a break point right at the return
in gdb do
b main.c:x
where x is the line number of the return statement
After calling the UIApplicationMain function your application launches (establishing a runloop, etc) and all work should then be done outside the context of main (if you need it to run in main, do it before that point). When quitting an application it is generally more efficient to allow the OS to do memory cleanup.
I have that not return experience too. And have set break points to verify exactly like Clint said.
wisequark has a good point.
great topic. makes me feel more comfortable that i am not the only one who has the question.