문제

내 소프트웨어를 사용하는 클라이언트 중 한 명이 막다른 상황에 처해 있습니다.판매된 약 40개의 제품 중(VB.NET 2005를 사용하여 .NET 2.0으로 프로그래밍된 응용 프로그램) 약 2개는 듀얼 코어 CPU 중 1개의 코어가 100%에서 멈춰 응답하지 않습니다(프로그램은 1개의 코어만 사용).

가장 논리적인 추측은 이 동작을 일으키는 무한 루프이지만, 이는 수많은 루프가 포함된 수천 줄의 코드입니다.제가 아는 정보는 이게 전부입니다.이제 이 문제를 디버깅하는 방법에 대해 어떻게 제안하시겠습니까?

편집하다:기본적으로 소프트웨어는 PC 등 다른 장치를 사용하여 소비된 크레딧 금액을 계산하는 역할을 합니다.Cybercafe 관리 프로그램이며 간헐적으로 실패합니다.실패하면 크레딧을 차감합니다.특히 데이터베이스 백업을 생성할 시간인지 확인하는 등 백그라운드에서 다른 작업도 수행합니다.

편집하다:해결되었습니다.가장 가능성이 낮은 문제였습니다.제가 DBMS로 사용한 Access Database Engine은 실제로 제 애플리케이션에서 문제가 있는 부분입니다.테이블 중 하나에 있는 행(JUST ONE FRIGGIN ROW)을 작업하는 데 어려움이 있습니다.삭제할 수 없으며 다른 테이블의 해당 행과 관련된 레코드를 추가할 수도 없습니다.MS Access 2007에서도 해당 행으로 작업하려고 하면 CPU 성능이 100%까지 올라갑니다!

간단한 "Compact and Repair" 명령으로 모든 것이 해결되었습니다.내 응용 프로그램이 시작될 때마다 해당 명령을 실행할 것 같습니다.그러면 이런 일이 다시는 발생하지 않게 될 것입니다.

WinDbg 덕분에 문제가 있는 곳을 찾을 수 있었습니다.시간을 절약해 주기 때문에 모든 사람에게 사용 방법을 배우는 것이 좋습니다.

도움이 되었습니까?

해결책

대상 머신에 windbg(Windows 디버거)를 설치합니다.디버거를 호출하고 의심스러운 프로세스에 연결한 후 프로그램을 실행하고 문제가 발생할 때까지 기다립니다.문제가 발생하면 디버거 명령줄에서 다음 명령을 호출하십시오.

!도망자

그러면 어느 스레드가 대부분의 시간을 소비하는지 알 수 있습니다.그런 다음 대부분의 CPU 리소스를 소비하는 스레드에서 여러 스레드 스택을 가져옵니다.

예는 다음과 같습니다.

0:015> !runaway

사용자 모드 시간 스레드 시간 0 : 1074 0 일 0 : 00 : 21.637 11 : 137C 0 일 0 : 00 : 02.792 4 : 12C8 0 일 0 : 00 : 00.530 9 : 1374 0 일 0 : 00 : 00.046 15 : 13d0 0 일 0 : 00 : 00.000 14 : 1204 0 일 0 : 00 : 00 : 00.000 13 : 154c 0 일 0 : 00 : 00.000 12 : 144c 0 일 0 : 00 : 00.000 10 : 1378 0 일 0 : 00 : 00.000 8 : 1340 0 일 0 : 00 : 00.000 7 : 12f0 0 일 0 : 00 : 00 : 00.000 6 : 12d4 0 일 0 : 00 : 00.000 5 : 12d0 0 일 0 : 00 : 00.000 3 : 12C4 0 일 0 : 00 : 00.000 2 : 12C0 0 일 0 : 00 : 00.000 1 : 12B4 0 일 0 : 00 : 00.000

이제 목록의 두 번째 스레드인 스레드 11에 대한 호출 스택을 원한다고 가정하고 먼저 스레드 11로 전환합니다.~11s를 입력하면 이 작업을 수행할 수 있습니다.

0:015> ~11s

EAX = 03FBB270 EBX = FFFFFFFF ECX ​​= 00000002 EDX = 00000060 ESI = 00000000 EDI = 00000000 EIP = 77475E74 ESP = 0572F60C EBP = 0572F67C IOPL = 0 NV UP EI PL ZR NA CS = 001B SS = 001B SS = 001B = 0023 FS = 003B GS = 0000 EFL = 00000246 NTDLL! KIFASTSYSTEMCALLRET :77475e74 c3 레트

이제 kp를 실행하여 이 스레드에 대한 호출 스택을 가져옵니다.

0:011> kp
ChildEBP RetAddr  
0572f608 77475620 ntdll!KiFastSystemCallRet
0572f60c 75b09884 ntdll!NtWaitForSingleObject+0xc
0572f67c 75b097f2 kernel32!WaitForSingleObjectEx+0xbe
*** ERROR: Symbol file could not be found.  Defaulted to export symbols for C:\Program Files\Mozilla Firefox 3.1 Beta 1\nspr4.dll - 
0572f690 10019a0b kernel32!WaitForSingleObject+0x12
WARNING: Stack unwind information not available. Following frames may be wrong.
0572f6ac 10015979 nspr4!PR_MD_WAIT_CV+0x8b
0572f6c4 10015763 nspr4!PR_GetPrimordialCPU+0x79
*** ERROR: Symbol file could not be found.  Defaulted to export symbols for C:\Program Files\Mozilla Firefox 3.1 Beta 1\xul.dll - 
0572f6e0 64d44d6a nspr4!PR_Wait+0x33
0572f708 64dbe67e xul!NS_CycleCollectorForget2_P+0x698a
0572f72c 10019b3f xul!gfxWindowsPlatform::FontEnumProc+0xfd4e
0572f734 10015d32 nspr4!PR_MD_UNLOCK+0x1f
0572f738 1001624b nspr4!PR_Unlock+0x22
0572f754 1001838d nspr4!PRP_TryLock+0x4cb
00000000 00000000 nspr4!PR_Now+0x109d

kp 명령은 매개변수를 인쇄합니다.지역 변수는 dv로 인쇄할 수 있습니다.

또는 sysinternals의 프로세스 탐색기를 사용할 수 있습니다.

원격 클라이언트 시스템이기 때문에 이 모든 것이 가능하지 않은 경우 userdump를 설치하면 추가 분석을 위해 사용자에게 보낼 수 있는 덤프 파일이 생성됩니다.고객이 올바른 매개변수를 사용하여 userdump를 호출하도록 배치 파일을 생성할 수 있습니다.Userdump는 Microsoft의 웹 페이지에서 다운로드할 수 있는 도구입니다.

다른 팁

가능하면 프로세스 덤프를 받고 스택 추적을보십시오.
나는 결코 그렇게하지 않았지만 VS/WINDBG 및 SOS (스트라이크의 아들)와 함께 작동해야합니다. 여기에 있습니다 블로그 게시물 그것에 대해.

무한 루프 인 경우 디버거를 부착하고 파손을 해보십시오. WindBG는 이에 이상적입니다.

이 기술은 루프가 너무 많이 반복되는 경우에도 효과가 있지만 결국 나머지 코드와 함께 진행됩니다. 좋은 샘플을 얻기 위해 절차를 반복하는 데 몇 분을 소비 할 수 있습니다.

이 기술은 여러 번 저를 저축했으며 Hung Applications에도 잘 작동합니다. :)

글쎄, 당신은 그것이 꽉 루핑되는 곳을 알아 내야합니다. 고객은 당시 소프트웨어로 무엇을하고 있습니까? 소프트웨어는 처음에 무엇을합니까?

코드에 많은 로깅을 추가하고 클라이언트에 로깅이 활성화 된 모든 것을 사용하여 클라이언트에 사본을 제공하여 문제가있는 곳을 추적하는 데 도움이 될 수 있습니다.

로거를 사용하십시오 log4net 기존 코드베이스를 소개 할 수 있습니다 포스트 쇼트. 모든 메소드 항목 및 종료를 기록하므로 결함이있는 메소드를 찾아야합니다. 그런 다음 여전히 필요한 경우 로깅을 개선 할 수 있습니다.

경험이 없지만 VB.net에서도 작동하는 것 같습니다. 아마도 이 기사 조금 도움이됩니다.

그 고객을 매우 철저히 인터뷰해야합니다. 항상 쉬운 것은 아니지만 문제를 좁히는 것은 유일한 샷입니다.

그런 다음 추적을 조심스럽게 추가하고 전략적 지점 (또는 자동 플러시를 설정하는 것을 잊지 마십시오.

그러나 추적의 지연이 추가되어 사라지는 미묘한 타이밍 문제 일 수 있습니다 ...

배경 스레드가 UI를 업데이트하려고 할 때와 같이 단일 코어 및 멀티 코어 CPU가 다르게 작동하는 데 문제가있을 수 있습니다.

(그리고 나는 배경과 UI 스레드를 깨끗하게 분리하지 않은 암흑 시대에 앱을 썼고 멀티 코어 CPU가 주류를 얻었을 때 문제를 일으켰다는 것을 인정합니다. 솔루션은 앱을 단일 코어로 제한하기 위해 SetProcessAffinity를 호출하는 것이 었습니다).

이 경우 100% CPU가 특별한 종류의 CPU로만 발생하는지 여부와 SetProcessAffinity를 사용하여 문제가 해결되는지 확인해야합니다. 그렇다면 코드에서 어디에서 찾아야하는지 알고 있습니다.

스레딩 문제 일 수 있습니까? "간헐적으로 실패한다"는 것을 생각하게한다. 프로그램은 원격/DCOM/소켓과 같이 외부에서 신호/메시지를 받습니까? 이러한 메시지와 관련된 진행 정보는 사용자 인터페이스에 제시되어 있습니까?

나는 항상 많은 어설 팅을 사용하기 때문에 나사산 문제를 감지했습니다. XML-RPC를 통해 수신 된 메시지의 시작에 대한 정신 점검 주장이 다음과 같습니다.

"<?xml " 

그리고 주장은 메시지의 기억을 덮어 쓰는 것을 포착했다. 검사를 통해 이것은 임계 섹션에서 누락 된 잠금으로 인한 것으로 판명되었습니다. 이 검출은 문제가 인식에 의해 너무 일찍 잡히기 때문에 가능했습니다 (그리고 자주 감지하기에 충분히 자주 발생했습니다).

이것은 매우 명백하거나 지시 된 조언은 아니지만, 내 제안은 스레딩 문제에 영향을받을 수있는 장소에 어셈블리를 추가하는 것입니다.

해고 어설 션이 반드시 프로그램을 중단하거나 메시지 상자를 던지는 것을 의미하는 것은 아닙니다. 어설 싱 발사시 전체 스택 트레이스를 포함하여 대신 로그 파일로 리디렉션 될 수 있습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top