#objective-c #cocoa #macos #exc-bad-access
#objective-c #cocoa #macos #исключение-bad-access
Вопрос:
Вообще говоря, как нам избежать сбоев objc_msgSend() в наших приложениях для Mac? Кроме того, как нам избежать сбоев EXC_BAD_ACCESS? Почему мы это получаем? Как мы можем справиться с такого рода ошибками? Их количество в нашем приложении увеличивается, и мы хотели бы попросить совета и помощи по этому вопросу.
Мы используем XCode 3.2.5, и наш проект является проектом Cocoa, использующим язык Objective-C. Наш веб-сервис представляет собой ASP на базе IIS.Веб-сайт Net (откуда мы можем загружать XML-файлы и изображения).
Мы разрабатываем cocoa-приложение для Mac, и мы сталкиваемся с этим примерно два раза за десять попыток запуска приложения. В этом приложении есть приложение sketch, и когда мы запускаем приложение, оно просто зависает и выходит из строя в течение 1 минуты, ничего не делая. Некоторые функции, которые выполняет это приложение, это:
- загружайте xml из Интернета и интерпретируйте в нашем приложении
- войдите в веб-службу
- имеет блокнот для рисования
- имеет таймер
- функции перетаскивания
- загрузка XML-данных
- загружайте изображения и отображайте в нашем приложении
Сбой не ограничивается периодом после запуска приложения. Иногда при манипуляциях с программой, таких как перетаскивание, загрузка набора данных и выполнение функций добавления / редактирования / удаления в нашем приложении для Mac, приложение также вылетает.
Честно говоря, мы относительно новички в этой платформе разработки и среде, и мы все еще учимся. Можете ли вы помочь нам в этом вопросе? Нужны какие-то ресурсы или подсказки о том, где мы сделали это неправильно? Большое спасибо и больше энергии всем присутствующим.
Следующий пример отчета о сбое:
Process: Sketch [63065]
Path: /Users/william_hooley_27Inch/Desktop/untitled folder/MacGlass.app/Contents/MacOS/Sketch
Identifier: com.apple.CocoaExamples.Sketch
Version: 1.049 (48.1)
Code Type: X86 (Native)
Parent Process: launchd [116]
Date/Time: 2011-04-14 13:12:15.421 1000
OS Version: Mac OS X 10.6.5 (10H574)
Report Version: 6
Interval Since Last Report: 714907 sec
Crashes Since Last Report: 17
Per-App Interval Since Last Report: 206437 sec
Per-App Crashes Since Last Report: 5
Anonymous UUID:
086C860F-E28E-4256-84F9-9692782AAD01
Exception Type: EXC_BAD_ACCESS
(SIGBUS) Exception Codes:
KERN_PROTECTION_FAILURE at
0x0000000000000044 Crashed Thread: 0
Dispatch queue: com.apple.main-thread
Thread 0 Crashed: Dispatch queue:
com.apple.main-thread 0
com.apple.AppKit
0x91a8e6cb
_recursiveInvalidateCachedVisibleRectValue
24 1 com.apple.CoreFoundation 0x995f02c0 CFArrayApplyFunction 224
2 com.apple.AppKit
0x91a8e70d
_recursiveInvalidateCachedVisibleRectValue
90 3 com.apple.CoreFoundation 0x995f02c0 CFArrayApplyFunction 224
4 com.apple.AppKit
0x91a8e70d
_recursiveInvalidateCachedVisibleRectValue
90 5 com.apple.CoreFoundation 0x995f02c0 CFArrayApplyFunction 224
6 com.apple.AppKit
0x91a8e70d
_recursiveInvalidateCachedVisibleRectValue
90 7 com.apple.CoreFoundation 0x995f02c0 CFArrayApplyFunction 224
8 com.apple.AppKit
0x91a8e70d
_recursiveInvalidateCachedVisibleRectValue
90 9 com.apple.CoreFoundation 0x995f02c0 CFArrayApplyFunction 224
10 com.apple.AppKit
0x91a8e70d
_recursiveInvalidateCachedVisibleRectValue
90 11 com.apple.CoreFoundation 0x995f02c0 CFArrayApplyFunction 224
12 com.apple.AppKit
0x91a8e70d
_recursiveInvalidateCachedVisibleRectValue
90 13 com.apple.CoreFoundation 0x995f02c0 CFArrayApplyFunction 224
14 com.apple.AppKit
0x91a8e70d
_recursiveInvalidateCachedVisibleRectValue
90 15 com.apple.AppKit 0x91a8e2e1 -[NSView _setSuperview:]
684 16 com.apple.AppKit
0x91a8db02 -[NSView addSubview:] 383
17 com.apple.CocoaExamples.Sketch
0x00094cbf -[viewTasksDisplay Appear:]
242 18 com.apple.CocoaExamples.Sketch
0x000c2e8f -[MainWindow
ShowLeftScreen:] 964 19
com.apple.CocoaExamples.Sketch
0x0003e301 -[viewOptionMenuItemmouseDown:] 2055 20
com.apple.AppKit
0x91bc6c68 -[NSWindow sendEvent:]
5549 21 com.apple.AppKit
0x91adf817 -[NSApplication sendEvent:]
6431 22 com.apple.AppKit 0x91a732a7 -[NSApplication run] 917
23 com.apple.AppKit
0x91a6b2d9 NSApplicationMain 574 24
com.apple.CocoaExamples.Sketch
0x0001b33e main 30 25
com.apple.CocoaExamples.Sketch
0x00001eba start 54 Thread 1:
Dispatch queue:
com.apple.libdispatch-manager 0
libSystem.B.dylib
0x98002982 kevent 10 1
libSystem.B.dylib
0x9800309c _dispatch_mgr_invoke 215
2 libSystem.B.dylib
0x98002559 _dispatch_queue_invoke
163 3 libSystem.B.dylib
0x980022fe _dispatch_worker_thread2
240 4 libSystem.B.dylib
0x98001d81 _pthread_wqthread 390 5
libSystem.B.dylib
0x98001bc6 start_wqthread 30 Thread
2: 0 libSystem.B.dylib
0x97fdc0fa mach_msg_trap 10 1
libSystem.B.dylib
0x97fdc867 mach_msg 68 2
com.apple.CoreFoundation
0x995f837f __CFRunLoopRun 2079
Еще один отчет о сбое:
Date/Time: 2011-04-14 13:27:02
1000 OS Version: 10.6.5 (Build 10H574) Architecture: x86_64 Report
Version: 6 Command: MacGlass
Path:
/Users/william_hooley_27Inch/Desktop/untitled
folder/MacGlass.app/Contents/MacOS/Sketch
Version: 1.050 (48.1) Parent:
launchd [116] PID: 63101
Event: hang Duration:
3.58s (sampling started after 2 seconds) Steps: 16 (100ms
sampling interval) Pageins: 0
Pageouts: 0 Process:
Sketch [63101] Path:
/Users/william_hooley_27Inch/Desktop/untitled
folder/MacGlass.app/Contents/MacOS/Sketch
UID: 501 Thread edef3d4
DispatchQueue 100 User stack:
16 start 54 (in Sketch) [0x1f6a]
16 main 30 (in Sketch) [0x1b3ee]
16 NSApplicationMain 574 (in AppKit) [0x91a6b2d9]
16 -[NSApplication run] 821 (in AppKit) [0x91a73247]
16 -[NSApplication nextEventMatchingMask:untilDate:inMode:dequeue:]
156 (in AppKit) [0x91ab0fce]
16 _DPSNextEvent 847 (in AppKit) [0x91ab178d]
16 BlockUntilNextEventMatchingListInMode
81 (in HIToolbox) [0x95bd0bd6]
16 ReceiveNextEventCommon 354 (in
HIToolbox) [0x95bd0d51]
16 RunCurrentEventLoopInMode 392 (in
HIToolbox) [0x95bd0f9c]
16 CFRunLoopRunInMode 97 (in
CoreFoundation) [0x995f7291]
16 CFRunLoopRunSpecific 452 (in
CoreFoundation) [0x995f7464]
16 __CFRunLoopRun 8059 (in CoreFoundation) [0x995f9adb]
16 __NSFireTimer 141 (in Foundation) [0x972c39b0]
16 _handleWindowNeedsDisplay 696 (in AppKit) [0x91adb28a]
16 -[NSWindow displayIfNeeded] 204 (in AppKit) [0x91aa9d40]
16 -[NSView displayIfNeeded] 818 (in AppKit) [0x91ae0a57]
16 -[NSView _displayRectIgnoringOpacity:isVisibleRect:rectIsVisibleRectForView:]
4122 (in AppKit) [0x91b801cf]
16 CAViewEndDraw 134 (in QuartzCore)
[0x961bd926]
16 pthread_cond_wait$UNIX2003 73 (in
libSystem.B.dylib) [0x9800b9f8]
16 __semwait_signal 10 (in
libSystem.B.dylib) [0x9800a0a6]
Kernel stack:
15 semaphore_wait_continue 0 [0x22a3dd]
1 lo_alltraps 454 [0x2a08a6]
1 i386_astintr 47 [0x2a9a9a]
1 ast_taken 247 [0x219107]
1 bsd_ast 806 [0x489088]
1 postsig 432 [0x4861df]
1 exit1 449 [0x47ab28]
1 task_terminate_internal 315
[0x22c56a]
Комментарии:
1. И распространенной причиной
EXC_BAD_ACCESS
является неправильное управление памятью. Используете ли вы сборку мусора в своем приложении?2. Я рекомендую прочитать: Итак, вы потерпели крах в objc_msgSend()
Ответ №1:
Обычная причина чего-то подобного — чрезмерное высвобождение объектов. Если вы запускаете свой код с помощью NSZombieEnabled, вывод на консоль должен дать вам подсказку о том, где искать.
В качестве альтернативы, если это приложение для Macintosh, ориентированное на версию 10.5 или выше, вы можете включить сборку мусора и вообще не беспокоиться о сохранении и выпуске.
Ответ №2:
Когда эта ошибка возникает в приложении iOS на устройстве, подключенном к отладчику, вы можете узнать вызываемый селектор, введя в консоли отладки
(gdb) x / s $ r1
Это помогло мне найти проблему, когда для акселерометра все еще был установлен делегат на освобожденный объект. Возможно, эта информация полезна для других.
Комментарии:
1. ![введите описание изображения здесь][1] [1]: i.stack.imgur.com/otnqT.png Я делаю это неправильно?
2. Приведенный выше ответ был для gdb, но из вашего скриншота ясно, что вы используете lldb (который является отладчиком по умолчанию начиная с XCode 4.3). Информацию о том, как использовать lldb, можно найти здесь: lldb.llvm.org/tutorial.html
3. $ r1 — это не тот регистр, в котором он взорвался для меня с iOS 8. Следует смотреть на трассировку стека по мере изменения ситуации
Ответ №3:
Второй отчет о сбое — это не сбой, это отчет о зависании. Это означает, что ваше приложение работало медленно, а не зависало.
В общем, прочитайте и полностью поймите рекомендации по управлению памятью Cocoa; ошибки в управлении памятью являются причиной подавляющего большинства сбоев в приложениях Cocoa. Руководство можно найти здесь: https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/MemoryMgmt/Articles/MemoryMgmt.html
Вы также должны иметь возможность использовать такие инструменты, как отладчик Xcode и инструмент Zombies в Instruments, для сбора более подробной информации о сбоях.
Ответ №4:
Я смог найти проблемный селектор с помощью lldb, но подход для меня отличался от описанного в ответе выше, используя семантику gdb и более раннюю версию iOS (в настоящее время я работаю с iOS 8)
Моя трассировка стека начиналась так:
libobjc.A.dylib`objc_msgSend:
0x10c160000: testq %rdi, %rdi
0x10c160003: jle 0x10c160068 ; objc_msgSend 104
0x10c160005: movq (%rdi), %r11
0x10c160008: movq %rsi, %r10
0x10c16000b: andl 0x18(%r11), %r10d <== EXC_BAD_ACCESS
В приглашении lldb я выполнил следующее:
(lldb) register read -G s r10
r10 = "xffffffc16xffffffa4tx01" "isKindOfClass:"
Ответ №5:
Я только что решил проблему EXC_BAD_ACCESS в objc_msgSend, найдя, где я перезаписал конец строки, повредив объект в хранилище….
Ответ №6:
Проблема для меня заключалась в том, что я вызвал обработчик UIAleraction из селектора, который не был UIAleraction