我在我的应用程序 (SymSteam) 中发现了一个错误,修复起来特别困难。似乎每当我的应用程序作为登录项启动时,它都会成功启动,但几秒钟后就会崩溃。如果应用程序由用户启动(即通过 Finder),它会正常运行并且不会崩溃。
登录后立即检查控制台,我看到以下内容:
04/08/2012 18:51:47.437 SymSteam[187]: SteamApps exists & SteamAppsSymb exists, suggesting everything is A-OK.
04/08/2012 18:51:47.451 SymSteam[187]: Succesfully started observing everything I need to
04/08/2012 18:51:52.623 com.apple.launchd.peruser.501[124]: ([0x0-0x16016].com.simplecode.SymSteam[187]) Job appears to have crashed: Segmentation fault: 11
前两行表明我的应用程序启动正常,并且能够从 NSWorkspace 的通知中心注册所需的通知。但事后我无法弄清楚是什么导致了段错误。
还有一个崩溃报告。以下是其摘录:
OS Version: Mac OS X 10.8 (12A269)
Report Version: 10
Crashed Thread: 0 Dispatch queue: com.apple.main-thread
Exception Type: EXC_BAD_ACCESS (SIGSEGV)
Exception Codes: EXC_I386_GPFLT
Thread 0 Crashed:: Dispatch queue: com.apple.main-thread
0 libobjc.A.dylib 0x00007fff80902278 _cache_getImp + 4
1 libobjc.A.dylib 0x00007fff80903f51 lookUpMethod + 41
2 libobjc.A.dylib 0x00007fff80905d5e class_respondsToSelector + 31
3 com.apple.CoreFoundation 0x00007fff82adb7ab objectIsKindOfClass + 43
4 com.apple.CoreFoundation 0x00007fff82adb812 __exceptionMatch + 18
5 libobjc.A.dylib 0x00007fff8090d1d4 _objc_exception_do_catch(objc_typeinfo*, objc_typeinfo*, void**, unsigned int) + 144
6 libc++abi.dylib 0x00007fff81621807 get_adjusted_ptr(std::type_info const*, std::type_info const*, void**) + 71
7 libc++abi.dylib 0x00007fff81621439 __gxx_personality_v0 + 889
8 libunwind.dylib 0x00007fff8b678c22 _Unwind_RaiseException + 158
9 libc++abi.dylib 0x00007fff81621baa __cxa_rethrow + 72
10 libobjc.A.dylib 0x00007fff8090d5f5 objc_exception_rethrow + 40
11 com.apple.CoreFoundation 0x00007fff82a7ce36 CFRunLoopRunSpecific + 390
12 com.apple.HIToolbox 0x00007fff8c855774 RunCurrentEventLoopInMode + 209
13 com.apple.HIToolbox 0x00007fff8c855512 ReceiveNextEventCommon + 356
14 com.apple.HIToolbox 0x00007fff8c8553a3 BlockUntilNextEventMatchingListInMode + 62
15 com.apple.AppKit 0x00007fff87afefa3 _DPSNextEvent + 685
16 com.apple.AppKit 0x00007fff87afe862 -[NSApplication nextEventMatchingMask:untilDate:inMode:dequeue:] + 128
17 com.apple.AppKit 0x00007fff87af5c03 -[NSApplication run] + 517
18 com.apple.AppKit 0x00007fff87a9a656 NSApplicationMain + 869
19 com.simplecode.SymSteam 0x0000000108df4d54 start + 52
Thread 1:
0 libsystem_kernel.dylib 0x00007fff82dad6d6 __workq_kernreturn + 10
1 libsystem_c.dylib 0x00007fff84c27f2c _pthread_workq_return + 25
2 libsystem_c.dylib 0x00007fff84c27cf3 _pthread_wqthread + 412
3 libsystem_c.dylib 0x00007fff84c121b1 start_wqthread + 13
Thread 2:: Dispatch queue: com.apple.libdispatch-manager
0 libsystem_kernel.dylib 0x00007fff82dadd16 kevent + 10
1 libdispatch.dylib 0x00007fff81bafe26 _dispatch_mgr_invoke + 883
2 libdispatch.dylib 0x00007fff81bafa2a _dispatch_mgr_thread + 54
Thread 3:
0 libsystem_kernel.dylib 0x00007fff82dad6d6 __workq_kernreturn + 10
1 libsystem_c.dylib 0x00007fff84c27f2c _pthread_workq_return + 25
2 libsystem_c.dylib 0x00007fff84c27cf3 _pthread_wqthread + 412
3 libsystem_c.dylib 0x00007fff84c121b1 start_wqthread + 13
Thread 4:
0 libsystem_kernel.dylib 0x00007fff82dad6d6 __workq_kernreturn + 10
1 libsystem_c.dylib 0x00007fff84c27f2c _pthread_workq_return + 25
2 libsystem_c.dylib 0x00007fff84c27cf3 _pthread_wqthread + 412
3 libsystem_c.dylib 0x00007fff84c121b1 start_wqthread + 13
Thread 0 crashed with X86 Thread State (64-bit):
rax: 0x1000000000000000 rbx: 0x00007fff70bf5810 rcx: 0x0000000000000001 rdx: 0x0000000000000000
rdi: 0x1000000000000000 rsi: 0x00007fff88323f93 rbp: 0x00007fff56e0b910 rsp: 0x00007fff56e0b8d0
r8: 0x0000000000000000 r9: 0x0000000000000000 r10: 0x00000000510558d1 r11: 0x1000000000000000
r12: 0x0000000000000000 r13: 0x0000000000000000 r14: 0x1000000000000000 r15: 0x00007fff88323f93
rip: 0x00007fff80902278 rfl: 0x0000000000010202 cr2: 0x00007fff88424000
Logical CPU: 0
我对导致问题的原因感到困惑,因为应用程序在登录时未启动时不会崩溃,即使在登录时启动,它也会启动,但几秒钟后崩溃。我不知道如何调试这个错误,因为我无法设置断点或在程序上使用仪器,因为该错误仅在登录时发生。
非常感谢任何有关如何进行调试的建议!
就其值(value)而言,我的应用程序是后台应用程序(因此它没有停靠图标或主窗口),它使用 Growl & Sparkle框架并在启动时注册来自 NSWorkspace 的通知。
更新:
这是我的应用程序启动时执行的代码(applicationDidFinishLaunching:
方法中的一些不相关代码已被省略)。正如我上面所说,这一切都在崩溃之前执行。
applicationDidFinishLaunching方法:
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification{
[self.appController performInitialDriveScan];
[self.appController startWatchingDrives];
}
performInitialDriveScan:
只需使用 NSFileManager 几次来查看某些目录是否存在。我不会在这里发布它,因为它很长。我相当确信这不是崩溃的根源。
startWatchingDrives
:
- (void)startWatchingDrives{
[[[NSWorkspace sharedWorkspace] notificationCenter] addObserver:self.saController selector:@selector(didMountDrive:) name:NSWorkspaceDidMountNotification object:nil];
[[[NSWorkspace sharedWorkspace] notificationCenter] addObserver:self.saController selector:@selector(didUnMountDrive:) name:NSWorkspaceDidUnmountNotification object:nil];
NSLog(@"Succesfully started observing everything I need to");
}
这只是向 NSWorkspace 的通知中心添加了一个观察者,用于监视正在安装/卸载的驱动器。
这就是应用程序启动期间执行的所有内容。崩溃发生在调用 startWatchingDrives
方法之后,并且如上所述,仅在登录时启动应用程序时发生。当我的应用程序实际上没有做任何事情时就会发生这种情况。
最佳答案
我做了更多的调试并设法解决了我自己的问题。崩溃的总体原因非常无趣,但它是:
当用户登录时,应用程序正常启动,并且正在注册从 NSWorkspace 装载/卸载驱动器的通知。注册通知后几乎立即,它会在登录期间收到两个关于安装/home 和/net 的通知。 didMountDrive:
选择器由通知执行,在 didMountDrive:
方法中,我试图获取刚刚安装的驱动器的 URL 的第三个路径组件(因为,如果安装的是外部驱动器,则这将是驱动器的名称)。这就是程序崩溃的地方,因为/home 和/net URL 只有两个路径组件,所以我试图访问 URL 的 pathComponents 数组范围之外的索引。
修复方法只是检查刚刚安装的驱动器的 URL 中是否至少有 3 个路径组件。
关于objective-c - Cocoa 应用程序在登录时启动时崩溃,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11811119/