Write to console synchronously - iphone

I need to debug a time-critical crash I have in my App and since NSLog does not immediately write to the console I am wondering if there is a way to synchronously write to the console from my code.
So for example is printf a better choice here or would I have to deal with the same problems.

You can add a breakpoint before the crashing line(s), though I think Xcode by default already hangs the proccess so that you can still access the debugger console ... If it doesn't, you may want to add some additional diagnostics by going to Product -> Edit Scheme .. (in the upper menu), such as Guard Edges, Zombie Objects, etc.
In addition, you can call NSLog from the main thread:
[self performSelectorOnMainThread:#selector(log:) withObject:#"String .." waitUntilDone:YES];
- (void)log:(NSString *)message {
NSLog(message);
}

Related

How to debug iPhone applications

how can i debug applications for iPhone in Objective-C, XCode
i mean ok, XCode and debug mode is fine, but when my application crashes on
BAD_ACCES (or smth. smilliar) i just get the trace to assembly
when iam debugging C++ and lets say want to access an invalid pointer, i get a trace right to the line of code where everything crashed... here i just get a trace to many internal functions in assembly, so i dont have a clue what and where went wrong
probably some release / retain problem, but how can i find out?
thank you
Here we go with the full answer:
I've had a look at your app and I think there is a problem with the combination of the UINavigationController and asynchronous http loading in two places. Enabling the zombies did reveal those two errer. The first on I was able to reproduce, the seconds one popped up several times and then not any more.
*** -[DetailViewController respondsToSelector:]: message sent to deallocated instance 0x56d6030
*** -[SearchViewController respondsToSelector:]: message sent to deallocated instance 0x56daa10
I've just throttled my bandwidth to see if those errors are connected to http requests. Look at [Throttling Bandwidth On A Mac][1] to set up a slow connection. I set it to 5KBytes/sec.
The first error occurs if you go very quickyl down to the details and then two levels up again and as a last action to trigger the error: click on search. The stacktrace shows a
#2 0x004545b8 in -[UIWebView webView:decidePolicyForMIMEType:request:frame:decisionListener:]
and there are some threads open, so looking at the dropdown, there is a webThread. Showing that thread reveals something going on with the webview loading the detailPages url. This hints that the webiew actually finished loading in a seperate thread and wasn't able to connect back to the webview itself [DetailViewController respondsToSelector:]. This can be easily proofed: remove the loading of the request for the webview: I wasn't able to reproduce the error.
Solution problem 1
The problem is easily fixed, as the webview is not released in the dealloc. Setting delegates to nil of objects is also recommended, but not needed in this case.
- (void)dealloc {
webView.delegate = nil;
[webView release];
}
The second error
The stackTrace shows a
CLLocationManager onClientEventLocation:
Solution error
Same as error 1, set the delegate to nil and release the locationManager.
When your app crashes you cann open up the debugger in the left hand window you can see the stacktrace. You can double click any line which will jump to correct position in your code(if the called method is of yours).
Goto Project->Edit Active Executable->Arguments Tab
Add the Variable in the lower window by clicking on +
Name:NSZombieEnabled
Value:YES
This tries to resolve memory addresses to class names for bad excess errors.
To find out about memory leaks, open Run->Run with performance tool->Leaks. This will open up instruments which is a brillant tool to find leaks.
Are you using XCode 3? If so, I would highly advise upgrading to XCode 4. The debugger in XCode 4 is brilliant in comparison. It let's you step back through the code and see exactly what caused the crash.

Tracing the method calls in iPhone app

How can I trace the method calls and their sequence while a iPhone app is running? Which Instrument I should use?
No Instrument does this directly. A couple of options to get this kind of information:
1) Set a breakpoint in the debugger. You can then trace the execution with the "step over" "step into" and "step out" buttons.
2) Put NSLogs at the places in your code that interest you:
-(void) someMethod {
NSLog (#"Starting someMethod");
// rest of the method is here
}
You can then read the NSLogs in the console.
you can also use
NSLog(#"%s",__PRETTY_FUNCTION__);
to print the method that is currently running

Stack trace or more info on unhandled exception in Xcode/iPhone

Excuse my ignorance, but something's been bugging me about the Xcode debugger when running iPhone applications in the iPhone Simulator.
Sometimes, when I mess something up in Interface Builder, I get an unhandled exception at runtime and I get thrown back to Xcode. The only thing I see is a single line "uncaught exception" or something like that. From what I can see, there's no additional information, let alone a stack trace or anything else that's useful.
I have been developing in Visual Studio for the last decade or so, and I'm used to getting a nice stack trace and complete exception info when something like that happens.
I'm sure I'm simply missing something very obvious... Hopefully...
If you add two breakpoints, you should be able to debug these exceptions. To do this, go to Run | Show | Breakpoints and create two global breakpoints (I do them globally because they are so useful in all my applications). The first should be named "objc_exception_throw" and its location should be "libobjc.A.dylib". The second should be "-[NSException raise]" and its location should be "CoreFoundation".
Now, if you start debugging your application with breakpoints enabled, it should break on the throw of these exceptions. You should then be able to see the chain of events that led to the exception within the debugger.
The lack of a stack trace is usually indicative of a problem with LLDB (debugger). I love LLDB, but when it comes to showing stack traces and breaking on the exception rather than main in iOS apps, it's a pain in the ass and has been for a few releases now. No idea why Apple hasn't addressed this yet. To fix it is a two-step process:
Edit your current scheme and under the "Run" tab change the debugger from LLDB to GDB.
Go to https://developer.apple.com/bugreporter/ and report the bug so Apple addresses it.
Hey activa - for more information about runtime exceptions, you should be able to open the debugger console and see more information. I assume you've already done that, but just in case - you can get to it by selecting Run -> Console from the menu. I'm not sure why it doesn't come up automatically!
You can wrap your UIApplicationMain in a try/catch:
int main(int argc, char *argv[]) {
int retVal;
NSAutoreleasePool * pool;
#try
{
pool = [[NSAutoreleasePool alloc] init];
retVal = UIApplicationMain(argc, argv, nil, nil);
}
#catch(NSException* e)
{
NSLog(#"%#", e.reason);
}
#finally
{
[pool release];
}
return retVal;
}
You should also look up into setting an assertion handler while debugging: NSAssertionHandler.
Update:
and also the unhandled exception handler: NSSetUncaughtExceptionHandler

NSZombieEnabled doesn't report the type of object causing an EXC_BAD_ACCESS error

I have a crash that is happening deep within UIKit for some reason; an EXC_BAD_ACCESS error is happening something like 8 calls deep into a dismissModalViewController call. I tried enabling NSZombieEnabled for my executable, but the console log prints the same error regardless of whether or not zombies are turned on and i don't know which object is causing the issue. Is there something i'm missing that i need to do to get the console to print the correct information?
Read about using Zombies here.
Run this in gdb. When you get the EXC_BAD_ACCESS look at the stack at that point (use gdb's where command or run the Xcode GUI debugger). If you are still having issues, post the stack in your original question.
Also zombies will only help you if you're dealing with NSObjects. If you're using low level malloc/free routines zombies buy you nothing for those allocations.
One thing I learned last weekend when NSZombieEnabled didn't seem to be working at all - make sure you're not passing in a non-object to some code.
In my case, I was returning an NSString as just "string" instead of #"string". That meant I was overwriting an NSString object with the c-string. When I later tried to write a new value in that object I was getting a BAD_ACCESS. NSZombie's couldn't help b/c it was not an object I was trying to overwrite, but that c-string.
As an aside, treat all warnings as errors in XCode - wish I could make them show up in RED in the IDE GUI - they are easy to miss sometimes.
Sounds like something is over-released in your Modal View Controller. Start by commenting out newish lines until it stops breaking.

What's the best way to log debug info in an iphone app?

Is there some standard way or has anyone written something that allows you to log a message and have it be displayed either in a small scrolling section on the iphone screen or in a separate window in the iphone simulator?
Update:
For noobs like me and don't know, use the NSLog methods as decribed below and make sure you select Run->Console to display the console.
Would still like to know if anyone has written a simple logger that displays on the iphone itself....
I don't have enough 'reputation' to add a direct comment for your posting but: don't forget to go to XCode->Preferences->Debugging->On Start: Choose Show Console & Debugger
You can of course choose just the Console or whatever, but you'll probably want the Debugger to. To use that, just click to the left of the line you want to break at. You can also toggle from 'Activate' to 'Deactivate' so you if you know that there are a bunch of breakpoints you don't need to hit in the beginning of your application set the debugging to Deactive (in the debugging window) and then, before you hit the UI element in your app you want to debug, toggle that same button to Activate so your breakpoints become active. Otherwise, you could of course just click Continue until you got to your section.
Also, on the NSLog, if you start to accumulate a bunch of log statements, and you need to 'find' one in particular, it helps to do: NSLog(#"\n\n\nMy statement\n\n\n); which will give a bunch of line breaks. Also, for the uninitiated:
NSLog(#"My int: %d my BOOL: %d", myInt, myBOOL);
NSLog(#"My object of any NSObject: %#", anObjectOfAnyKind);
NSLog(#"My float: %f",myFloat);
Hope all of this is helpful and sorry if I got off track with the debugging bit ;)
The Objective-C (more correct, really) method is
NSLog(#"message");
But the standard C method will work also
printf("message");
Use NSLog(#"Log message");
If your have an application that is crashing then your can ask the users you the crash log. The crash log contains information about what the application was doing when it crashed and the stack trace.
iPhone app log files are also stored on your users computer, and are copied across everytime they sync their iPhone. ( Note that DEVICE_NAME will be the same name of your iPhone in iTunes, and each log file will begin with the name of the app. )
Mac OS X : /Library/Logs/CrashReporter/MobileDevice//
Windows XP: C:\Documents and Settings\Application Data\Apple computer\Logs\CrashReporter\
Windows Vista: C:\Users\AppData\Roaming\Apple computer\Logs\CrashReporter\MobileDevice\
For Swift, it's simply
print("log msg")