2013-04-26 3 views
4

내 프로그램이 매우 어려운 재현 버그로 고통 받고있는 것처럼 보입니다. 파란 달에 한 번 사용자가 Mac을 잠자기 상태로 만들고 다시 켜면 내 프로그램의 하위 프로세스 중 하나가 즉시 중단됩니다 맥이 깨어 난 후에충돌 후 "불가능한"스택 추적은 무엇을해야합니까?

이 애플의 충돌 기자 메커니즘이 안정적으로 이와 같은 스택 추적보고 일 : 제외

Thread 0 Crashed:: Dispatch queue: com.apple.main-thread 
0 libsystem_kernel.dylib   0x967f9a6a __pthread_kill + 10 
1 libsystem_c.dylib    0x9003dacf pthread_kill + 101 
2 libsystem_c.dylib    0x900744f8 abort + 168 
3 com.meyersound.VirtualD-Mitri 0x0014438e muscle::CrashSignalHandler(int) + 190 
4 libsystem_c.dylib    0x9002886b _sigtramp + 43 
5 ???        0xffffffff 0 + 4294967295 
6 com.meyersound.VirtualD-Mitri 0x001442d0 muscle::ParsePortArg(muscle::Message const&, muscle::String const&, unsigned short&, unsigned long) + 80 
7 com.meyersound.VirtualD-Mitri 0x005b3393 qnet::RepDBPeer::Pulse(muscle::PulseNode::PulseArgs const&) + 1187 
8 com.meyersound.VirtualD-Mitri 0x0015717b muscle::PulseNode::PulseAux(unsigned long long) + 203 
9 com.meyersound.VirtualD-Mitri 0x000cfb90 muscle::ReflectServer::ServerProcessLoop() + 3232 
10 com.meyersound.VirtualD-Mitri 0x00607c7e dcasldmain(int, char**) + 2222 
11 com.meyersound.VirtualD-Mitri 0x0072c14d dmitridmain(int, char**) + 4749 
12 com.meyersound.VirtualD-Mitri 0x0000bc3a main + 4938 
13 com.meyersound.VirtualD-Mitri 0x000061ab _start + 209 
14 com.meyersound.VirtualD-Mitri 0x000060d9 start + 41 

이, 잘하고 좋은는 (큐 섬뜩한 음악) -이 논리적으로 불가능입니다. 특히 내 RepDBPeer::Pulse() 메서드는 ParsePortArg을 호출하지 않을뿐만 아니라 충돌 프로세스가 ParsePortArg을 호출하지 않습니다.! (나는 두 번 내 소스 코드를 모두 두 번 확인했다.)

내 질문은 무엇입니까? 이것은 스레드 0의 스택이 스택 트레이스 메커니즘이 레일에서 빠져 나와 무고한 구경꾼을 범인으로 몰아 먹을 정도로 손상되었을 가능성이 가장 큽니까? 아니면 애플의 웨이크 업 메커니즘이 어째 든 프로그램 카운터를 ParsePortArg()로 "점프"했을 가능성이 있습니다 (충돌로 인해 혼란이 생겼습니다)? 아니면 내가 생각조차 할 수없는 더 깊은 마법이 여기에 있습니까?

문제의 충돌 프로세스는 Qt GUI 프로세스에 의해 생성 된 자식 프로세스 인 바닐라가 아닌 GUI 백그라운드 프로세스입니다.

+1

나는 이름이 지정된 함수를 그렇게 보지 않고 호출 할 수있는 상황을 생각하려고합니다. 매크로와 함수 포인터는 즉시 뛰어납니다. 이 함수는 분명히 정의되어 있습니다. ParsePortArg가있는 다른 곳을 볼 수 있습니까? –

+0

아마도 무거운 최적화. grep은 변수에이 함수가 어떻게 든 전달되면 도움이되지 않습니다. – Elazar

+1

예외는 스택에서 비표준 프레임을 밀어 넣고 unwind 코드가 항상이를 인식하지는 않습니다. –

답변

1

일부 최적화 기능을 사용한다고 가정합니다. 흔적을 쌓을 마법은 없습니다. 코드가 인라인되거나 생략되면 C++ 옵티마이 저가 수행하는 코드가 점점 더 퍼지게됩니다 ("덜 정확함"으로 읽음). ParsePortArg의 경우 코드 세그먼트에서 해당 함수의 진입 점보다 80 바이트 앞의 해당 줄 끝에 +80이 있습니다. 이것은 명령어 포인터의 실제 주소가 0x001442d0이고, ParsePortArg이 스택 덤프가 추측 한 가장 가까운 심볼임을 나타냅니다. 당신은 빨간 청어라고 생각하는 것이 옳았습니다.

다른 데이터가 없다면, 프로그램이 일부 포인터가 잠자기에서 깨어날 때 유효하지 않은 상태로 유지 될 것으로 매우 보수적으로 추측합니다. 그 주소의 지시에 대한 해체를보십시오. 나는 메모리 주소가 읽히려고 노력하고있다.

+0

감사합니다. 매우 도움이되었습니다. 디스 어셈블리를 검사 할 때 ("otool -tv MyApp.app/Contents/MacOS/MyApp "실행 파일에서 ParsePortArg()가 CrashSignalHandler()에 인접 해 있다는 것을 알 수 있습니다. 실제로는 CrashSignalHandler() 함수 였을 때 오프셋이 스택 추적 생성기를 속여 ParsePortArg()를 인쇄해야했습니다. 스택에. –