Сбой во время операций перетаскивания в приложении C++/Objective-C в OSX

У меня есть большое приложение на C++ с некоторыми смешанными Objective-C, созданным с помощью XCode 5. В одном представлении приложения есть список элементов. Перетаскивание элементов списка будет нормально работать в течение 5, 10 или 50 раз, но в конечном итоге приложение будет зависать при перетаскивании. Он никогда не падает при запуске из XCode (сборка выпуска или отладки). Он не падает, когда я запускаю сборку отладки извне. Вылетает только при запуске сборки релиза извне.

Вот фрагмент кода, который начинает операцию перетаскивания (сбой происходит перед возвратом из dragImage):

// start drag
m_bDragging = true;
[[pHost getView]
    dragImage:pDragImage
    at:ptOffset.getNSPoint()
    offset:NSZeroSize
    event:pEvent
    pasteboard:[NSPasteboard pasteboardWithName:NSDragPboard]
    source:[pHost getView]
    slideBack:YES];
m_bDragging = false;

[pHost getView] возвращает указатель на переменную-член NSView. Это не улучшает поведение, чтобы обеспечить NULL для dragImage и события. У монтажной панели есть список имен файлов, связанных с элементами списка.

Вот типичный отчет о сбое (в котором всегда есть CFSetGetValue):

Exception Type:  EXC_BAD_ACCESS (SIGSEGV)
Exception Codes: KERN_INVALID_ADDRESS at 0x0000025900000100

VM Regions Near 0x25900000100:
CG shared images       00000001c871f000-00000001c8727000 [   32K] r--/r-- SM=SHM
-->
JS JIT generated code  00002ece70800000-00002ece70801000 [    4K] ---/rwx SM=NUL

Thread 0 Crashed:: Dispatch queue: com.apple.main-thread
0   com.apple.CoreFoundation        0x00007fff9a8c06a9 CFSetGetValue + 25
1   com.apple.CoreFoundation        0x00007fff9a8d81df __CFRunLoopFindMode + 223
2   com.apple.CoreFoundation        0x00007fff9a902a39 CFRunLoopAddTimer + 153
3   com.apple.HIServices            0x00007fff9265bf15 StartIPCPing + 166
4   com.apple.HIToolbox             0x00007fff986956bf __DragInfoPtrSetValueForKey + 160
5   com.apple.HIToolbox             0x00007fff98695616 __CoreDragSetValueForKey + 52
6   com.apple.AppKit                0x00007fff905c968d __50-[NSDragDestination _resetUpdateDraggingItemTimer]_block_invoke + 164
7   libdispatch.dylib               0x00007fff96beb1bb _dispatch_call_block_and_release + 12
8   libdispatch.dylib               0x00007fff96be828d _dispatch_client_callout + 8
9   libdispatch.dylib               0x00007fff96bf0433 _dispatch_after_timer_callback + 77
10  libdispatch.dylib               0x00007fff96be828d _dispatch_client_callout + 8
11  libdispatch.dylib               0x00007fff96bea885 _dispatch_source_invoke + 413
12  libdispatch.dylib               0x00007fff96befe97 _dispatch_main_queue_callback_4CF + 244
13  com.apple.CoreFoundation        0x00007fff9a9404f9 __CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__ + 9
14  com.apple.CoreFoundation        0x00007fff9a8fb714 __CFRunLoopRun + 1636
15  com.apple.CoreFoundation        0x00007fff9a8fae75 CFRunLoopRunSpecific + 309
16  com.apple.HIToolbox             0x00007fff98634a0d RunCurrentEventLoopInMode + 226
17  com.apple.HIToolbox             0x00007fff986347b7 ReceiveNextEventCommon + 479
18  com.apple.HIToolbox             0x00007fff986345bc _BlockUntilNextEventMatchingListInModeWithFilter + 65
19  com.apple.AppKit                0x00007fff902bb24e _DPSNextEvent + 1434
20  com.apple.AppKit                0x00007fff902ba89b -[NSApplication nextEventMatchingMask:untilDate:inMode:dequeue:] + 122
21  com.apple.AppKit                0x00007fff905c9170 NSCoreDragBlockingProc + 107
22  com.apple.HIServices            0x00007fff9265a230 SampleMouseAndKeyboard + 102
23  com.apple.HIServices            0x00007fff92659f50 DragInApplication + 50
24  com.apple.HIServices            0x00007fff92659177 CoreDragStartDragging + 519
25  com.apple.AppKit                0x00007fff905c5a54 -[NSCoreDragManager _dragUntilMouseUp:accepted:] + 862
26  com.apple.AppKit                0x00007fff9077d3a4 -[NSCoreDragManager dragImage:fromWindow:at:offset:event:pasteboard:source:slideBack:] + 1355
27  com.apple.AppKit                0x00007fff90a6385b -[NSWindow(NSDrag) d

Другой аварийный журнал начался как это:

2014-09-04 19:47:59.659 myApp[47690:507] -[__NSCFNumber member:]: unrecognized selector sent to instance 0x5907
2014-09-04 19:47:59.687 myApp[47690:507] An uncaught exception was raised
2014-09-04 19:47:59.688 myApp[47690:507] -[__NSCFNumber member:]: unrecognized selector sent to instance 0x5907
2014-09-04 19:47:59.688 myApp[47690:507] (
    0   CoreFoundation                      0x00007fff9a9d925c __exceptionPreprocess + 172
    1   libobjc.A.dylib                     0x00007fff92958e75 objc_exception_throw + 43
    2   CoreFoundation                      0x00007fff9a9dc12d -[NSObject(NSObject) doesNotRecognizeSelector:] + 205
    3   CoreFoundation                      0x00007fff9a937272 ___forwarding___ + 1010
    4   CoreFoundation                      0x00007fff9a936df8 _CF_forwarding_prep_0 + 120
    5   CoreFoundation                      0x00007fff9a8c0721 CFSetGetValue + 145

У меня нет идей. Любая помощь будет оценена, спасибо.

1 ответ

Решение

Это ошибка управления памятью в вашем коде. Второй аварийный журнал показывает сообщение -member: был отправлен объекту, который не отвечает на него (NSNumber), что настоятельно предполагает, что целью сообщения должен был быть класс, который отвечает на -member:, Это большая подсказка, потому что, держу пари, это ваш собственный код. В какой-то момент вы пытаетесь отправить сообщение объекту после его освобождения. Может быть, вы забыли оставить где-нибудь затянутую вещь? Может быть, вы переиздали (если вы не используете ARC или сборщик мусора)? У вас есть свисающая ссылка, которую вы не обнулили? Не знаю.

Инструмент, который вы должны использовать, это Инструменты, с инструментом Зомби. Запустите приложение, сделайте его аварийное завершение, затем позвольте инструментам пометить точку, в которой вы "отправили сообщение объекту-зомби" (в этом случае инструмент фактически не освобождает объекты, а скорее сохраняет их вокруг и помечает их как "зомби"). - объекты нежити - и следит за сообщениями, отправленными объектам, которые должны были быть освобождены после того, как их количество сохраненных достигло нуля). Нажмите на стрелку в всплывающем сообщении и обратите самое пристальное внимание на весь срок службы этого объекта (с точки зрения того, где он был создан, а также всех сохраненных / выпущенных сообщений, отправленных и откуда). Это единственный надежный способ отследить ошибку такого рода: заставить ее выйти из строя во время работы под инструментом "Зомби" в инструментах.

Другие вопросы по тегам