论坛里经常有朋友会问Crash的问题。Crash最多的无非就两种,一种就是signal SIGABRT,大概的意思就是发送Message出现问题,信号迷失了。
这种的Crash其实是很好定位,Crash了后直接看Console里出的最后日志,比如这段:
1 |
2012-03-28 19:26:33.055 TableViewMenuDemo[3916:f803] *** Terminating app due to uncaught exception ‘NSInvalidArgumentException’, reason: ‘-[__NSArrayI replaceObjectAtIndex:withObject:]: unrecognized selector sent to instance 0x6a3f3d0′ |
2 |
3 |
*** First throw call stack: |
找到reason字段,那就是原因,说NSArray 调用 replaceObjectAtIndex:withObject:
这个方法是NSMutableArry的,NSArray并没有该方法。信号迷失掉了,所以Crash了。0x6a3f3d0 是出问题的内存地址,查下内存地址或搜下调用方法就比较好定位了。
看图在工程的左边栏中选择Breakpoint Navigator ,点击下面的+号添加一个Exception Breakpoint,然后再运行试试,Crash后,是不是直接定位到了那行代码了?再根据Console里的日志进行定位修改就好了。
下面说说另一种Crash,EXC_BAD_ACCESS ,这个比较头疼,因为Crash的时候,可能是比较早之前的某个变量释放了,现在访问时出问题。Console里也没显示什么日志。
这里光加入Exception Breakpoint是不够的了,XCode4还个可爱的地方,打开Scheme选项选择Edit Scheme
这样重新跑一下,如果是到Exception Breakpoint处停止了,可以在Console中输入:c(continue)按回车继续跑,直到Crash。看下Console是不是有跟SIGABRT类似的错误信息日志了,后面定位什么的你懂的。
如果还没有日志,在Console中输入 po $eax $eax标志出错的地方,适用模拟器,真机用$r0(话说EXC_BAD_ACCESS这种错误模拟器定位就行),还可以输入比如:po [$eax name] po [$eax reason]等指令查看错误其他信息(注意方括号后没分号的)。然后,就没有然后了。
还要补充点,程序开发过程就要多关注左边栏中Issue Navigator里的警告信息,Xcode4不仅会警告,还多数给出解决建议。能避免后面不必要的Crash
iPhone-NSAssert使用
调试cocoa程序在程序出错时,不会马上停止。使用宏NSAssert可以让程序出错时马上抛出异常。
在debug情况下,所有NSAssert都会被执行。在release下不希望NSAssert被执行,我们通常在release种将断言设置成禁用。
设置方法:在targets种选择build,选择release。在gcc preprocessing下增加Preprocessor Macros 值为 NS_BLOCK_ASSERTIONS.
C语言调试用NSCAssert.
//=============================================================================================================================
使用Xcode 4编译器设定Release/Debug教程
使用Xcode4编译器设定Release/Debug教程是本文要介绍的你内容,主要是来学习xcode 4的相关内容,让我们更一步的去熟悉、了解xcode 4,内容不多,不过真的可以帮助友们去解决xcode 4中编译器的问题。先来看内容。
进入Xcode 4,选择菜单“Product”->“Manage Schemes”,出现下图:
Bulid Configuration
在调试中,如果需要传入参数,在上图中Arguments上设置。
一般这个设置常用于控制台程序,比如:A.exe -p boy
那么,在Arguments上添加-p boy
说明下,在XCode上,可以这么设定,如图所示:
另外:追加编译宏:选择项目,找到“Bulid Setting”,下面有一项:Preprocessor Macros。
小结:使用Xcode4编译器设定Release/Debug教程的内容介绍完了,希望本文对你有所帮助!
======================================= 技巧3========================================xcode4 设置调试错误信息小结
方案1:NSZombieEnabled
先选中工程, 依次 "Product"-"Edit Scheme", 左栏选择"Run...", 右栏选中Arguments,然后在Environment Variables下面添加以下三个属性, 设值为YES
NSDebugEnabled
NSZombieEnabled
NSAutoreleaseFreedObjectCheckEnabled
有时候在程序出错的时候能准确定位到奔溃的那一行,或者会给你下面这样的提示,而不仅仅是EXEC_BAD_ACCESS:
message sent to deallocated instance 0x126550
如果要查看上面地址的分配情况
开启MallocStackLogging(Xcode4勾选下MallocStackLogging就行)
出错时shell malloc_history pid address
另:有时候可以重载respondsToSelector可以帮你找到程序崩溃时最后执行的函数,然后排查.
方案2:添加全局断点
Xcode4可以很方便的添加全局的异常断点
方案3:中断和未捕获异常
1.未拦截信号来源:内核,其他程序,本身.
常见的两个信号:
1).EXC_BAD_ACCESS试图访问非法内存,导致SIGBUS或者SIGSEGV信号
2).未能拦截obj_exception_throw导致的SIGABRT信号.
2.方法
1).使用NSUncaughtionHandler安装一个handler拦截未拦截异常
2).使用signal函数安装一个handler拦截BSD信号.(SIGKILL[kill-9]和SIGSTOP[Control+z]无法拦截)
两个c函数
- void SignalHandler(int signal)
- {
- //中断信号
- }
- void uncaughtExceptionHandler(NSException *exception)
- {
- //未捕获异常
- }
安装(与全局异常断点冲突,当有这样的断点是,下面拦截函数失效)
- void InstallUncaughtExceptionHandler()
- {
- NSSetUncaughtExceptionHandler(&uncaughtExceptionHandler);
- signal(SIGABRT, SignalHandler);
- signal(SIGILL, SignalHandler);
- signal(SIGSEGV, SignalHandler);
- signal(SIGFPE, SignalHandler);
- signal(SIGBUS, SignalHandler);
- signal(SIGPIPE, SignalHandler);
- }
3.具体实例
1.http://cocoawithlove.com/2010/05/handling-unhandled-exceptions-and.html
重点在于尝试继续运行程序
告诉用户那些因为这些未拦截的异常和信号导致的崩溃,或者自己记录,甚至可以避开这样导致的崩溃.不过,如果多个信号拦截了,这可能失效.
非常推荐看看这篇文章
2.http://parveenkaler.com/2010/08/11/crashkit-helping-your-iphone-apps-suck-less/
重点在于记录异常(之后返回主线程)
- - (void)pumpRunLoop
- {
- self.finishPump = NO;
- CFRunLoopRef runLoop = CFRunLoopGetCurrent();
- CFArrayRef runLoopModesRef = CFRunLoopCopyAllModes(runLoop);
- NSArray * runLoopModes = (NSArray*)runLoopModesRef;
- while (self.finishPump == NO)
- {
- for (NSString *mode in runLoopModes)
- {
- CFStringRef modeRef = (CFStringRef)mode;
- CFRunLoopRunInMode(modeRef, 1.0f/120.0f, false); // Pump the loop at 120 FPS
- }
- }
- CFRelease(runLoopModesRef);
- }
SIGKILL,程序在ios4下启动不了
再次启动程序时程序启动不了.
在真机测试有时能起来有时起不来,如果起不来关机再开机,再启动就能起来
请问1. "SIGKILL"是什么情况下产生的?
2. 如何解决?
注释:单击home是后台挂起,在双击home后才退出。
有哪位大侠知道敬请指教!不慎感激!
plist 加上UIApplicationExitsOnSuspend bool 值
參考這裡
UIApplicationExitsOnSuspend = Application does not run in background