iOS Crash(崩溃)调试技巧

【Linux】进程间通信之信号篇 今天我们来看进程间通信中唯一的异步通信机制----->信号我们之前看过信号量,信号量的本质是一个计数器;千万不要跟今天的信号搞混,Linux中的信号是向进程异步发送的事件通知,通知进程有事件(硬件异常、程序执行异常、外部发出信号)发生。进程间可以相互发送信号,内核也可能在内部发送信号。当信号产生时,内核向进程发送信号(在进程所在的进程表项的信号域设置对应于该信号的位图的比特位为0或者为1),... 阅读详情

转自:http://www.yifeiyang.net/iphone-development-skills-of-debugging-articles-3-crash-after-debugging-skills-program/


iPhone开发技巧之调试篇(3)— 程序Crash后的调试技巧

当我们的程序突然死掉了,Xcode突然送出一段 "message sent to deallocated instance" 的错误,我们该怎样定位我们的程序bug呢?

又或者我们已经通过AdHoc发布了我们的β版程序,更甚至于我们的程序已经发布到了app store上;而当我们的程序突然在测试人员,或者是最终用户那里突然当掉,是否能收集到这样的日志信息,供我们解析bug呢?

下面的文章中我将逐步深入地说明这些技巧

模拟器上显示堆栈信息

当我们在模拟器上调试时,可能经常遇到下面的内存访问错误:

1
2011-01-17 20:21:11.41 App[26067:207] *** -[Testedit retain]: message sent to deallocated instance 0x12e4b0

dealloced

首先,我们为了定位问题,需要Xcode帮我们显示栈信息,可以通过Scode中执行文件的属性来设置。如下图所示,选中 MallocStackLogging 选项。该选项只能在模拟器上有效,并且如果你改变了iOS的版本后也需要再次设定该选项。

MallocStackLogging

这之后,你就可以在终端输入 info malloc-history 命令,如下所示;

1
(gdb) info malloc-history 0x12e4b0

之后得到如下的堆栈信息,从此分析具体的问题所在。

MallocStackLogging

除此之外,也可以使用下面的命令;

1
(gdb) shell malloc_history {pid/partial-process-name} {address}

例如下图所示;

EXC_BAD_ACCESS

另外,内存使用时“EXC_BAD_ACCESS”的错误信息也是经常遇到的,这时我们只要将上面执行文件属性中的 NSZombieEnabled 选上,也能定位该问题。

最后,这些设置信息都是可以在运行期确认的,如下;

1
NSLog(@"NSZombieEnabled: %s", getenv("NSZombieEnabled"));

在iPhone上输出日志

如果不是在模拟器上,又或者我们的设备没有连接到PC上,那么如何调试我们的程序呢?假如我们通过AdHoc发布了程序,希望随时得到测试人员的反馈,可以利用下面的方法,将标准出力(stderr)信息记录到文件中,然后通过邮件新式发给开发者。

1. 设置一个开关,用来清空日志文件内容,并切换输出位置;

1
2
3
4
5
6
7
8
- (BOOL)deleteLogFile {

    [self finishLog];
    BOOL success = [[NSFileManager defaultManager] removeItemAtPath:[self loggingPath] error:nil];
    [self startLog];
    return success;

}

当我们调用上面的deleteLogFile后,就会清空之前的日志,并设置新的输出。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
- (void)finishLog {

    fflush(stderr);
    dup2(dup(STDERR_FILENO), STDERR_FILENO);
    close(dup(STDERR_FILENO));

}

- (NSString*)loggingPath {

    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *documentsDirectory = [paths objectAtIndex:0];
    NSString *logPath = [documentsDirectory stringByAppendingPathComponent:@"console.log"];
    return logPath;

}

- (void)startLog {
   freopen([[self loggingPath] cStringUsingEncoding:NSASCIIStringEncoding],"a+",stderr);
}

2. 当日志取得之后,可以通过下面的方式发送邮件给开发者

1
2
3
4
5
6
7
8
9
10
11
- (void)sendLogByMail {

    MFMailComposeViewController *picker = [[MFMailComposeViewController alloc] init];
    picker.mailComposeDelegate = self;
    [picker setSubject:[NSString stringWithFormat:@"%@ - Log", [self appName]]];
    NSString *message = [NSString stringWithContentsOfFile:[self loggingPath] encoding:NSUTF8StringEncoding error:nil];
    [picker setMessageBody:message isHTML:NO];
    [self.navigationController presentModalViewController:picker animated:YES];
    [picker release];

}

iPhone应用程序的CrashReporter机能

苹果在固件2.0发布的时候,其中一项特性是向iPhone开发者通过邮件发送错误报告,以便开发人员更好的了解自己的软件运行状况。不过不少开发者报告此服务有时无法获取到~/Library/Logs/CrashReporter/MobileDevice directory的错误信息。

现在苹果提供了一种更简单的方法,使iPhone开发者可以通过iTunes更容易的查看崩溃报告。具体方法使进入iTunesConnect(在进入之前确定你有iPhone开发者帐号),点击管理你应用程序,之后就可以看到用户崩溃日志了。

这里我介绍一下从设备中取出CrashLog,并解析的方法。

CrashLog的位置

程序Crash之后,将设备与PC中的iTunes连接,设备中的CrashLog文件也将一并同步到PC中。其中位置如下;

1
2
3
4
5
6
7
8
Mac:
~/Library/Logs/CrashReporter/MobileDevice

Windows Vista/7:
C:\Users\<user_name>\AppData\Roaming\Apple computer\Logs\CrashReporter/MobileDevice

Windows XP:
C:\Documents and Settings\<user_name>\Application Data\Apple computer\Logs\CrashReporter

在这些目录下,会有具体设备的目录,其下就是许多*.crash的文件。

比如程序TestEditor在iPhone1设备上的crashLog如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
~Library/Logs/CrashReporter/MobileDevice/iPhone1/TestEditor_2010-09-23-454678_iPhone1.crash

Incident Identifier: CAF9ED40-2D59-45EA-96B0-52BDA1115E9F
CrashReporter Key:   30af939d26f6ecc5f0d08653b2aaf47933ad8b8e
Process:         TestEditor [12506]
Path:            /var/mobile/Applications/60ACEDBC-600E-42AF-9252-42E32188A044/TestEditor.app/TestEditor
Identifier:      TestEditor
Version:         ??? (???)
Code Type:       ARM (Native)
Parent Process:  launchd [1]

Date/Time:       2010-09-23 11:25:56.357 +0900
OS Version:      iPhone OS 3.1.3 (7E18)
Report Version:  104

Exception Type:  EXC_BAD_ACCESS (SIGBUS)
Exception Codes: KERN_PROTECTION_FAILURE at 0x00000059
Crashed Thread:  0

Thread 0 Crashed:
0   UIKit                           0x332b98d8 0x331b2000 + 1079512
1   UIKit                           0x3321d1a8 0x331b2000 + 438696
2   UIKit                           0x3321d028 0x331b2000 + 438312
3   UIKit                           0x332b9628 0x331b2000 + 1078824
4   UIKit                           0x33209d70 0x331b2000 + 359792
5   UIKit                           0x33209c08 0x331b2000 + 359432
6   QuartzCore                      0x324cc05c 0x324ae000 + 122972
7   QuartzCore                      0x324cbe64 0x324ae000 + 122468
8   CoreFoundation                  0x3244f4bc 0x323f8000 + 357564
9   CoreFoundation                  0x3244ec18 0x323f8000 + 355352
10  GraphicsServices                0x342e91c0 0x342e5000 + 16832
11  UIKit                           0x331b5c28 0x331b2000 + 15400
12  UIKit                           0x331b4228 0x331b2000 + 8744
13  TestEditor                      0x00002c3a 0x1000 + 7226
14  TestEditor                      0x00002c04 0x1000 + 7172
... (以下略)

虽然我们看到了出为题时的堆栈信息,但是因为没有符号信息,仍然不知道到底哪里出问题了...

.dSYM文件

编译调试相关的符号信息都被包含在编译时的 xxxx.app.dSYM 文件当中,所以我们在发布程序前将它们保存起来,调试Crash问题的时候会很有用。

首先,我们来找到该文件。

用Xcode编译的程序,在其编译目录下都会生成 [程序名].app.dSMY 文件,比如 Xcode 4 的编译目录缺省的是

1
2
3
4
5
~Library/Developer/Xcode/DerivedData

# 在改目录下搜寻编译后的.dSMY文件
$ cd ~/Library/Developer/Xcode/DerivedData
$ find . -name '*.dSYM'

另外,我们也可以通过 Xcode的Preferences... -> Locations -> Locations 的Derived Data来确认该目录的位置。

上面例子中的程序,我们就找到了其位置是
1
~/Library/Developer/Xcode/DerivedData/TestEditor-aahmlrjpobenlsdvhjppcfqhogru/ArchiveIntermediates/TestEditor/BuildProductsPath/Release-iphoneos/TestEditor.app.dSYM

※ 大家每次像App Store发布自己程序的时候都记着保存该文件哦,要不然出现Crash的时候,就无从下手了。

解决符号问题

接下来,我们再来介绍一下使用.dSYM文件来恢复程序符号的方法。

首先,使用一个Xcode提供的叫做 symbolicatecrash 的小工具,它可以实现我们在CrashLog中添加符号信息的机能。该文件位于下面的位置,为方便起见,可以把它拷贝到系统默认路径下。

1
2
3
/Developer/Platforms/iPhoneOS.platform/Developer/Library/PrivateFrameworks/DTDeviceKit.framework/Versions/A/Resources/symbolicatecrash

$ sudo cp /Developer/Platforms/iPhoneOS.platform/Developer/Library/PrivateFrameworks/DTDeviceKit.framework/Versions/A/Resources/symbolicatecrash /usr/local/bin
使用下面的命令,可以在终端输出有符号信息的CrashLog
1
2
3
$ symbolicatecrash [CrashLog file] [dSYM file]

$ symbolicatecrash TestEditor_2010-09-23-454678_iPhone1.crash TestEditor.app.dSYM
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
Thread 0 Crashed:
0   UIKit                           0x332b98d8 -[UIWindowController transitionViewDidComplete:fromView:toView:] + 668
1   UIKit                           0x3321d1a8 -[UITransitionView notifyDidCompleteTransition:] + 160
2   UIKit                           0x3321d028 -[UITransitionView _didCompleteTransition:] + 704
3   UIKit                           0x332b9628 -[UITransitionView _transitionDidStop:finished:] + 44
4   UIKit                           0x33209d70 -[UIViewAnimationState sendDelegateAnimationDidStop:finished:] + 284
5   UIKit                           0x33209c08 -[UIViewAnimationState animationDidStop:finished:] + 60
6   QuartzCore                      0x324cc05c _ZL23run_animation_callbacksdPv + 440
7   QuartzCore                      0x324cbe64 _ZN2CAL14timer_callbackEP16__CFRunLoopTimerPv + 156
8   CoreFoundation                  0x3244f4bc CFRunLoopRunSpecific + 2192
9   CoreFoundation                  0x3244ec18 CFRunLoopRunInMode + 44
10  GraphicsServices                0x342e91c0 GSEventRunModal + 188
11  UIKit                           0x331b5c28 -[UIApplication _run] + 552
12  UIKit                           0x331b4228 UIApplicationMain + 960
13  TestEditor                      0x00002c3a main (main.m:14)
14  TestEditor                      0x00002c04 0x1000 + 7172

由此,我们可以具体定位程序中出问题的地方。

用StackTrace取得崩溃时的日志

异常处理机制

任何语言都有异常的处理机制,Objective-C也不例外。与C++/Java类似的语法,它也提供@try, @catch, @throw, @finally关键字。使用方法如下。

1
2
3
4
5
6
7
8
9
10
11
12
@try {
...   }
@catch (CustomException *ce) {
...   }
@catch (NSException *ne) {
// Perform processing necessary at this level.
...  }
@catch (id ue) {
...   }
@finally {
// Perform processing necessary whether an exception occurred or not.
...   }

同时对于系统Crash而引起的程序异常退出,可以通过UncaughtExceptionHandler机制捕获;也就是说在程序中catch以外的内容,被系统自带的错误处理而捕获。我们要做的就是用自定义的函数替代该ExceptionHandler即可。

这里主要有两个函数
  • NSGetUncaughtExceptionHandler() 得到现在系统自带处理Handler;得到它后,如果程序正常退出时用来回复系统原先设置
  • NSSetUncaughtExceptionHandler() 红色设置自定义的函数
简单的使用例子如下所示
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
void MyUncaughtExceptionHandler(NSException *exception)
{
    printf("uncaught %s\n", [[exception name] cString]);
    // ~

    // 显示当前堆栈内容
    NSArray *callStackArray = [exception callStackReturnAddresses];
    int frameCount = [callStackArray count];
    void *backtraceFrames[frameCount];

    for (int i=0; i<frameCount; i++) {
        backtraceFrames[i] = (void *)[[callStackArray objectAtIndex:i] unsignedIntegerValue];
    }
}

int main()
{
    // ~
    NSUncaughtExceptionHandler *ueh = NSGetUncaughtExceptionHandler();
    NSSetUncaughtExceptionHandler(&MyUncaughtExceptionHandler);
    // ~
}

- (void)exit_processing:(NSNotification *)notification {
    NSSetUncaughtExceptionHandler(ueh);
}

- (void)viewDidLoad {
    // 这里重载程序正常退出时UIApplicationWillTerminateNotification接口
    UIApplication *app = [UIApplication sharedApplication];
    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(exit_processing:)
                                                 name:UIApplicationWillTerminateNotification
                                               object:app]
}
处理signal

使用Objective-C的异常处理是不能得到signal的,如果要处理它,我们还要利用unix标准的signal机制,注册SIGABRT, SIGBUS, SIGSEGV等信号发生时的处理函数。该函数中我们可以输出栈信息,版本信息等其他一切我们所想要的。

例子代码如下
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
#include <signal.h>

void stacktrace(int sig, siginfo_t *info, void *context)
{
    [mstr appendString:@"Stack:\n"];
    void* callstack[128];
    int i, frames = backtrace(callstack, 128);
    char** strs = backtrace_symbols(callstack, frames);
    for (i = 0; i <; frames; ++i) {
        [mstr appendFormat:@"%s\n", strs[i]];
    }
}

int main(int argc, char *argv[])
{
      struct sigaction mySigAction;
      mySigAction.sa_sigaction = stacktrace;
      mySigAction.sa_flags = SA_SIGINFO;

      sigemptyset(&mySigAction.sa_mask);
      sigaction(SIGQUIT, &mySigAction, NULL);
      sigaction(SIGILL , &mySigAction, NULL);
      sigaction(SIGTRAP, &mySigAction, NULL);
      sigaction(SIGABRT, &mySigAction, NULL);
      sigaction(SIGEMT , &mySigAction, NULL);
      sigaction(SIGFPE , &mySigAction, NULL);
      sigaction(SIGBUS , &mySigAction, NULL);
      sigaction(SIGSEGV, &mySigAction, NULL);
      sigaction(SIGSYS , &mySigAction, NULL);
      sigaction(SIGPIPE, &mySigAction, NULL);
      sigaction(SIGALRM, &mySigAction, NULL);
      sigaction(SIGXCPU, &mySigAction, NULL);
      sigaction(SIGXFSZ, &mySigAction, NULL);

      NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
      int retVal = UIApplicationMain(argc, argv, nil, nil);
      [pool release];
      return (retVal);
}
总结
综上所述,我们可以看到用StackTrace取得崩溃时日志的手顺如下
  • 用NSGetUncaughtExceptionHandler()取得当前系统异常处理Handler
  • 用NSSetUncaughtExceptionHandler()注册自定义异常处理Handler
  • 注册signal处理机制
    • 注册Handler中打印堆栈,版本号等信息
    • 必要的时候将其保存到dump.txt文件
  • 异常程序退出
  • 如果程序不是异常退出,则还原之前系统的异常处理函数句柄
  • 如果下次程序启动,发现有dump.txt的异常文件,启动邮件发送报告机制
整体的代码框架如下
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
#include <signal.h>

void stacktrace(int sig, siginfo_t *info, void *context)
{
    [mstr appendString:@"Stack:\n"];
    void* callstack[128];
    int i, frames = backtrace(callstack, 128);
    char** strs = backtrace_symbols(callstack, frames);
    for (i = 0; i <; frames; ++i) {
        [mstr appendFormat:@"%s\n", strs[i]];
    }
}

void MyUncaughtExceptionHandler(NSException *exception)
{
    printf("uncaught %s\n", [[exception name] cString]);
    // ~

    // 显示当前堆栈内容
    NSArray *callStackArray = [exception callStackReturnAddresses];
    int frameCount = [callStackArray count];
    void *backtraceFrames[frameCount];

    for (int i=0; i<frameCount; i++) {
        backtraceFrames[i] = (void *)[[callStackArray objectAtIndex:i] unsignedIntegerValue];
    }
}

int main(int argc, char *argv[])
{
      struct sigaction mySigAction;
      mySigAction.sa_sigaction = stacktrace;
      mySigAction.sa_flags = SA_SIGINFO;

      sigemptyset(&mySigAction.sa_mask);
      sigaction(SIGQUIT, &mySigAction, NULL);
      sigaction(SIGILL , &mySigAction, NULL);
      sigaction(SIGTRAP, &mySigAction, NULL);
      sigaction(SIGABRT, &mySigAction, NULL);
      sigaction(SIGEMT , &mySigAction, NULL);
      sigaction(SIGFPE , &mySigAction, NULL);
      sigaction(SIGBUS , &mySigAction, NULL);
      sigaction(SIGSEGV, &mySigAction, NULL);
      sigaction(SIGSYS , &mySigAction, NULL);
      sigaction(SIGPIPE, &mySigAction, NULL);
      sigaction(SIGALRM, &mySigAction, NULL);
      sigaction(SIGXCPU, &mySigAction, NULL);
      sigaction(SIGXFSZ, &mySigAction, NULL);

      // ~
      NSUncaughtExceptionHandler *ueh = NSGetUncaughtExceptionHandler();
      NSSetUncaughtExceptionHandler(&MyUncaughtExceptionHandler);
      // ~

      NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
      int retVal = UIApplicationMain(argc, argv, nil, nil);
      [pool release];
      return (retVal);
}

- (void)exit_processing:(NSNotification *)notification {
    NSSetUncaughtExceptionHandler(ueh);
}

- (void)viewDidLoad {
    // 这里重载程序正常退出时UIApplicationWillTerminateNotification接口
    UIApplication *app = [UIApplication sharedApplication];
    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(exit_processing:)
                                                 name:UIApplicationWillTerminateNotification
                                               object:app]
}
输入的CrashLog如下
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Signal:10
Stack:
0 TestEditor 0x0006989d dump + 64
1 TestEditor 0x00069b4b signalHandler + 46
2 libSystem.B.dylib 0x31dcd60b _sigtramp + 26
3 TestEditor 0x000252b9 -[PopClientcreateUnreadMessageWithUIDL:maxMessageCount:] + 76
4 TestEditor 0x00025b85 -[PopClientgetUnreadIdList:] + 348
5 TestEditor 0x000454dd -[Connection receiveMessages:] + 688
6 TestEditor 0x00042db1 -[Connection main] + 188
7 Foundation 0x305023f9 __NSThread__main__ + 858
8 libSystem.B.dylib 0x31d6a5a8 _pthread_body + 28
AppVer:TestEditor 1.2.0
System:iPhone OS
OS Ver:3.0
Model:iPhoneDate:09/06/08 21:25:59JST

其中从_sigtramp函数下面开始进入我们的程序,即地址0x000252b9开始。其所对应的具体文件名和行号我们能知道吗?

利用之前介绍的dSYM文件和gdb,我们可以得到这些信息。

1
2
3
4
5
6
7
cd $PROJ_PATH$/build/Release-iphoneos/TestEditor.app.dSYM/
cd Contents/Resources/DWARF
gdb TestEditor
gdb>info line *0x000252b9
Line 333 of "~/IbisMail/Classes/Models/PopClient.m";
starts at address 0x2a386 <-[PopClient retrieve:]+86> and
ends at 0x2a390 <-[PopClient retrieve:]+96>





iOS奔溃分析技巧-crash日志符号化 前言 iOS开发需要不停发版本,开发者要面临线上各种版本的奔溃日志(crash log),解决奔溃问题是移动开发者最日常的工作之一. 在实际的项目开发中,崩溃问题,依赖xcode,依赖于系统记录的崩溃日志或错误堆栈,在本地开发调试阶段,是没有问题的。 如果在发布的线上版本出现崩溃问题,开发者是无法即时准确的取得错误堆栈的,需要获取到crash日志,进行相应处理。 简单的崩溃还好说,复杂的崩... 阅读详情

相关推荐

1. Klipper从安装到运行

本文记录Klipper固件从安装,配置到运行的详细过程

weixin_42098934的博客 1万+

Linux 之常见信号与处理

Linux信号是一种进程间异步的通信机制,在实现上是一种软中断,信号可以导致一个正在运行的进程被中断,进而处理一个突发事件。Linux在/usr/include/asm-generic/signal.h中详细定义了信号的信号值,其内容如下: 1、信号的基本概念 #define SIGHUP 1 //连接断开 #define SIGINT 2 /...

王木木 710

DeepSpeed Zero3 Offload实战:从GCC版本检查到环境配置的完整避坑指南

本文是一份针对DeepSpeed Zero3 Offload部署的完整避坑指南。针对训练中常见的`AttributeError: ‘DeepSpeedCPUAdam‘ object has no attribute ‘ds_opt_adam`报错,文章深入剖析了其根源在于GCC编译器版本过低。指南提供了从系统GCC版本深度探查、安全启用高版本GCC环境,到DeepSpeed一致性安装验证的全链路实战方案,旨在帮助用户构建稳定的大模型训练环境。

weixin_29070721的博客 473

signal信号宏定义查看

 在下面的目录: [lk@localhost linux]$ vim /usr/include/bits/signum.h  

melody_1016的博客 1309

关于使用CMT2300A FIFO缓存区间设置为64Byte的问题

帮助你解决在使用CMT2300A 时遇到的各种问题,若有需要,请及时与我交流

teleger的博客 1428

华为ITR流程实战指南:从设计到落地的全流程解析(附完整方案下载)

本文深度解析华为ITR流程从设计到落地的全流程实战指南。ITR不仅是高效处理客户问题的“救火”系统,更是驱动产品改进、预防问题的企业“免疫系统”。文章详细拆解了流程设计的四步走策略、三层技术支持体系的组织保障、以闭环改进为核心的考核激励,并探讨了如何借鉴其精髓,优化自身问题管理,实现从被动响应到主动服务的跨越。

y2z3a4b5c的博客 377

iPhone开发技巧之调试篇— 程序Crash后的调试技巧

6十一/110 原文链接 : http://www.yifeiyang.net/iphone-development-skills-of-debugging-articles-3-crash-after-debugging-skills-program/ 转载请保留上面文字。 模拟器上显示堆栈信息 在iPhone上输出日志 iPhone应用程序的CrashReporter

Annie的专栏 2797

COMSOL介电弹性体数值仿真指南:预拉伸圆形DEA的稳态变形分析(II)

本期博客是《COMSOL介电弹性体数值仿真指南》系列博客中的一期。聚焦于介电弹性体驱动器(DEA)中最为经典的预拉伸圆形DEA驱动器构型,对其在COMSOL平台中的具体建模步骤进行介绍与讨论。

忘了面孔的Batou 353

iOS Crash 分析

EXC_BAD_ACCESS 是异常类型,这钟类型表示访问了已经被release或者不存在的对象,导致出错,有时候会运行正常,这种情况说明被release的内存,被重用了,这就是常说的僵尸信号, KERN_PROTECTION_FAILURE意思如下:  操作系统不允许用户访问(读/写)的内存地址类型,地址0x00000009就是这样的类型,经常导致的原因就是使用了从来都没有被初始化的

缘故的博客 708

基于共识的捆绑算法CBBA在多无人机多任务调度中的实现

在捆绑过程中,每个无人机根据自己的任务清单和其他无人机的任务清单,确定一个被称为“束”的集合。通过合理的任务分配和无人机协作,CBBA算法能够实现最优的任务调度,提高了多无人机系统的效率和执行能力。在每一轮迭代中,无人机根据自己的当前任务和位置信息将任务清单发送给其他无人机,并接收其他无人机发送过来的任务清单。通过比较其他无人机的任务清单和自身的任务清单,每个无人机可以更新自己的任务分配情况。在这一步中,每个无人机根据自己选择的新任务,更新自身的任务清单,并将更新后的清单发送给其他无人机。

持续更新 1154

自然语言处理:长文本场景下的关键词抽取实践

自然语言处理:长文本场景下的关键词抽取实践

丨汀、的博客 2076

IOS调试技巧:当程序崩溃的时候怎么办 iphone IOS

IOS调试技巧:当程序崩溃的时候怎么办 iphone IOS 分类: object-c2013-02-19 22:24 6594人阅读 评论(1) 收藏 举报 from:http://article.ityran.com/archives/1143 有这样一种情形:当我们正在快乐的致力于我们的app时,并且什么看都是无比顺利,但是突然,坑爹啊,它崩溃了。(悲伤地音乐响

klabcxy36897的专栏 620

【Claude】Extra inputs are not permitted 错误:代理剥离 Beta 标头的解决方案 bug报错已解决

深入分析Claude Code Extra inputs are not permitted 400错误的技术原理,解析代理剥离Beta标头的根因与多种修复方案。

一键难忘的博客 145

iOS崩溃调试的使用和技巧总结

在iOS开发调试过程中以及上线之后,程序经常会出现崩溃的问题。简单的崩溃还好说,复杂的崩溃就需要我们通过解析Crash文件来分析了,解析Crash文件在iOS开发中是比较常见的。 现在网上有很多关于解析崩溃信息的博客,但是大多质量参差不齐,或者有些细节没有注意到。今天写一篇博客总结一下我对崩溃调试的使用和技巧,如果有哪些错误或遗漏,还请指点,谢谢! 获取崩溃信息 在iOS

苏小妖的博客 769

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

锂电池充电器电路设计 里面有电路

锂电池充电器电路设计 里面有电路 3.7V升压到5V电路设计。

iOS崩溃调试

在iOS开发调试过程中以及上线之后,程序经常会出现崩溃的问题。简单的崩溃还好说,复杂的崩溃就需要我们通过解析Crash文件来分析了,解析Crash文件在iOS开发中是比较常见的。 现在网上有很多关于解析崩溃信息的博客,但是大多质量参差不齐,或者有些细节没有注意到。今天写一篇博客总结一下我对崩溃调试的使用和技巧,如果有哪些错误或遗漏,还请指点,谢谢!...

weixin_33695082的博客 93

深度学习工具包 DeepLearningToolbox

深度学习工具包Deprecation notice.-----This toolbox is outdated and no longer maintained.There are much better tools available for deep learning than this toolbox, e.g. [Theano](http://deeplearning.net/software/theano/), [torch](http://torch.ch/) or [tensorflow](http://www.tensorflow.org/)I would suggest you use one of the tools mentioned above rather than use this toolbox.Best, Rasmus.DeepLearnToolbox================A Matlab toolbox for Deep Learning.Deep Learning is a new subfield of machine learning that focuses on learning deep hierarchical models of data.It is inspired by the human brain's apparent deep (layered, hierarchical) architecture.A good overview of the theory of Deep Learning theory is[Learning Deep Architectures for AI](http://www.iro.umontreal.ca/~bengioy/papers/ftml_book.pdf)For a more informal introduction, see the following videos by Geoffrey Hinton and Andrew Ng.* [The Next Generation of Neural Networks](http://www.youtube.com/watch?v=AyzOUbkUf3M) (Hinton, 2007)* [Recent Developments in Deep Learning](http://www.youtube.com/watch?v=VdIURAu1-aU) (Hinton, 2010)* [Unsupervised Feature Learning and Deep Learning](http://www.youtube.com/watch?v=ZmNOAtZIgIk) (Ng, 2011)If you use this toolbox in your research please cite [Prediction as a candidate for learning deep hierarchical models of data](http://www2.imm.dtu.dk/pubdb/views/publication_details.php?id=6284)```@MASTERSTHESIS\{IMM2012-06284, author = "R. B. Palm", title = "Prediction as a candidate for learning deep hierarchical models of data", year = "2012",}```Contact: rasmusbergpalm at gmail dot comDirectories included in the toolbox-----------------------------------`NN/` - A library for Feedforward Backpropagation Neural Networks`CNN/` - A library for Convolutional Neural Networks`DBN/` - A library for Deep Belief Networks`SAE/` - A library for Stacked Auto-Encoders`CAE/` - A library for Convolutional Auto-Encoders`util/` - Utility functions used by the libraries`data/` - Data used by the examples`tests/` - unit tests to verify toolbox is workingFor references on each library check REFS.mdSetup-----1. Download.2. addpath(genpath('DeepLearnToolbox'));Example: Deep Belief Network---------------------```matlabfunction test_example_DBNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit RBM and visualize its weightsrand('state',0)dbn.sizes = [100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);figure; visualize(dbn.rbm{1}.W'); % Visualize the RBM weights%% ex2 train a 100-100 hidden unit DBN and use its weights to initialize a NNrand('state',0)%train dbndbn.sizes = [100 100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);%unfold dbn to nnnn = dbnunfoldtonn(dbn, 10);nn.activation_function = 'sigm';%train nnopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.10, 'Too big error');```Example: Stacked Auto-Encoders---------------------```matlabfunction test_example_SAEload mnist_uint8;train_x = double(train_x)/255;test_x = double(test_x)/255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit SDAE and use it to initialize a FFNN% Setup and train a stacked denoising autoencoder (SDAE)rand('state',0)sae = saesetup([784 100]);sae.ae{1}.activation_function = 'sigm';sae.ae{1}.learningRate = 1;sae.ae{1}.inputZeroMaskedFraction = 0.5;opts.numepochs = 1;opts.batchsize = 100;sae = saetrain(sae, train_x, opts);visualize(sae.ae{1}.W{1}(:,2:end)')% Use the SDAE to initialize a FFNNnn = nnsetup([784 100 10]);nn.activation_function = 'sigm';nn.learningRate = 1;nn.W{1} = sae.ae{1}.W{1};% Train the FFNNopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.16, 'Too big error');```Example: Convolutional Neural Nets---------------------```matlabfunction test_example_CNNload mnist_uint8;train_x = double(reshape(train_x',28,28,60000))/255;test_x = double(reshape(test_x',28,28,10000))/255;train_y = double(train_y');test_y = double(test_y');%% ex1 Train a 6c-2s-12c-2s Convolutional neural network %will run 1 epoch in about 200 second and get around 11% error. %With 100 epochs you'll get around 1.2% errorrand('state',0)cnn.layers = { struct('type', 'i') %input layer struct('type', 'c', 'outputmaps', 6, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %sub sampling layer struct('type', 'c', 'outputmaps', 12, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %subsampling layer};cnn = cnnsetup(cnn, train_x, train_y);opts.alpha = 1;opts.batchsize = 50;opts.numepochs = 1;cnn = cnntrain(cnn, train_x, train_y, opts);[er, bad] = cnntest(cnn, test_x, test_y);%plot mean squared errorfigure; plot(cnn.rL);assert(er<0.12, 'Too big error');```Example: Neural Networks---------------------```matlabfunction test_example_NNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);% normalize[train_x, mu, sigma] = zscore(train_x);test_x = normalize(test_x, mu, sigma);%% ex1 vanilla neural netrand('state',0)nn = nnsetup([784 100 10]);opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samples[nn, L] = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.08, 'Too big error');%% ex2 neural net with L2 weight decayrand('state',0)nn = nnsetup([784 100 10]);nn.weightPenaltyL2 = 1e-4; % L2 weight decayopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex3 neural net with dropoutrand('state',0)nn = nnsetup([784 100 10]);nn.dropoutFraction = 0.5; % Dropout fraction opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex4 neural net with sigmoid activation functionrand('state',0)nn = nnsetup([784 100 10]);nn.activation_function = 'sigm'; % Sigmoid activation functionnn.learningRate = 1; % Sigm require a lower learning rateopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex5 plotting functionalityrand('state',0)nn = nnsetup([784 20 10]);opts.numepochs = 5; % Number of full sweeps through datann.output = 'softmax'; % use softmax outputopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex6 neural net with sigmoid activation and plotting of validation and training error% split training data into training and validation datavx = train_x(1:10000,:);tx = train_x(10001:end,:);vy = train_y(1:10000,:);ty = train_y(10001:end,:);rand('state',0)nn = nnsetup([784 20 10]); nn.output = 'softmax'; % use softmax outputopts.numepochs = 5; % Number of full sweeps through dataopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, tx, ty, opts, vx, vy); % nntrain takes validation set as last two arguments (optionally)[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');```[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/rasmusbergpalm/deeplearntoolbox/trend.png)](https://bitdeli.com/free "Bitdeli Badge")

告别崩溃烦恼:PlayCover调试神器完全指南 — 从日志追踪到Crash深度分析

你是否曾遇到安装的应用突然闪退却找不到原因?或者想查看应用运行时的详细状态?本文将带你掌握PlayCover的调试工具套件,通过控制台日志与Crash报告分析,轻松定位并解决应用运行问题。读完本文,你将学会: - 实时查看应用运行日志的3种方法 - 启用Crash报告自动捕获的配置技巧 - 分析崩溃原因的关键指标识别 - 常见错误代码的解决方案 ## 日志系统核心组件解析 PlayCover的...

gitblog_00164的博客 544

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

获取普通用户 iOS 设备上的 Crash Log 的方法

From: http://blog.youkuaiyun.com/cococoolwhj/article/details/7459064   http://www.yifeiyang.net/iphone-development-skills-of-debugging-articles-3-crash-after-debugging-skills-program/   当我们的程序突然死掉了,X...

移动开发 286

调试技术转载链接汇总

1.一篇很赞的ios视图bug调试案例,技术和方法都值得借鉴~ http://www.cocoachina.com/ios/20150330/11435.html 2.ios ui调试 http://www.cocoachina.com/ios/20141224/10748.html 3.ios中的crash日志捕获原...

weixin_33801856的博客 83

利用第三方工具dSYM快速定位crash文件中崩溃的函数位置

原文转自:点击打开链接 app上线之后程序崩溃信息我们只能通过crash文件获取崩溃信息 , 但是crash文件中的都是一些16进制的数表示函数地址的 .  如下图,根本不能直接看到具体程序崩溃在什么地方 .  不用担心 , 只要你每次打包后.xcarchive文件没有删除就可以将16进制的函数地址转换成直观的函数方法名 . 在xcode中顶部菜单Window中点击organize

hanxiaodongruanjian的博客 881

iOS-Crash日志

Understanding Crash Reports on iPhone OShttps://developer.apple.com/videos/wwdc/2010/?id=317http://www.cnblogs.com/smileEvday/p/Crash1.htmlhttp://www.cocoachina.com/industry/20130725/6677.html   http:...

MinggeQingchun的博客 1140

苹果官方 Crash文件分析方法 (iOS系统Crash文件分析方法)

转自  http://www.tuicool.com/articles/VzEBBn       苹果官方 Crash文件分析方法 (iOS系统Crash文件分析方法)    对于提交的苹果官方的app,在审核的时候会给我们一些crash文件,对于这些有用的文件,里面是关于我们的bug的一些信息,那么该如何去调试呢  第一步:在任意目录创建一个目录,用来调试crash,我这里创建一个c...

Lonely_Devil的博客 1203

Understanding iOS Exception Types

When your iOS app crashes, we need to analyze the crash log to help identify the root cause of it. The crash could be a “Low Memory Crash” or a “Normal Crash with Exceptions“. When it comes with “Ex

sharpyl的专栏 2631

iOS之深入解析崩溃Crash的收集调试与符号化分析

一、Crash 类型 Crash 一般产生自 iOS 的微内核 Mach,然后在 BSD 层转换成 UNIX SIGABRT 信号,以标准 POSIX 信号的形式提供给用户。NSException 是使用者在处理 App 逻辑时,用编程的方法抛出。 iOS 端的 Crash 分为三类: Mach 异常:EXC_CRASH; UNIX 信号:SIGABRT; 系统崩溃而引起的程序 NSException 异常退出。 二、iOS 中的崩溃类型 ① EXC_BAD_ACCESS 在

╰つ栺尖篴夢ゞ 1万+

iOS崩溃日志crash logs追踪以及调试方法

在IOS程序开发和以及在真机运行程序时,经常会遇到程序crash的情况,从哪里可以获得crash的日志文件,以便更好的分析程序崩溃的原因,让应用更加完美。          在真机运行程序出现crash状况时,机器会自动产生log文件,它包含了在程序crash之前正在做什么的信息。在pc上对手机或者ipad设备进行同步,就可以将这些日志文件存储在电脑中。下面时如何找到这些日志文件: 1.同步你

Kikim的地盘 1万+

IOS调试技巧:当程序崩溃的时候怎么办

有这样一种情形:当我们正在快乐的致力于我们的app时,并且什么看都是无比顺利,但是突然,坑爹啊,它崩溃了。(悲伤地音乐响起) 我们需要做的第一件事就是:不要惊慌。 修复崩溃不是很困难的。假如你崩溃了,并且胡乱的改些东西,而且还在不停的念着咒语希望bug神奇的自

不只是写代码的程序员 3307
上一篇: 应用提交苹果商店时,填写资料中字段翻译
下一篇: 导出私有函数
StudyRecord
博客等级 码龄16年 96粉丝 114原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值