sourcecode

C 프로그래밍: pthread를 사용한 디버깅

copyscript 2023. 10. 21. 10:39
반응형

C 프로그래밍: pthread를 사용한 디버깅

제가 처음에 적응하기 어려웠던 것 중 하나는 C에서 pthread를 사용한 집중적인 경험 프로그램이었습니다.저는 실행될 다음 코드 라인이 무엇인지 정확히 알고 있었고 대부분의 디버깅 기법은 그 기대에 중점을 두고 있었습니다.

C에서 pthread로 디버깅할 수 있는 좋은 기술은 무엇입니까?추가 도구나 사용하는 도구 또는 디버깅에 도움이 되는 다른 도구 없이 개인 방법론을 제안할 수 있습니다.

추신: 저는 리눅스에서 gcc를 사용하여 C 프로그래밍을 하지만, 그것이 반드시 당신의 답변을 방해하지 않도록 합니다.

Valgrind는 인종 조건과 pthread API 오용을 찾아내는 데 탁월한 도구입니다.프로그램 메모리 모델(및 공유 리소스) 액세스를 유지하며 버그가 양성일 때에도 잠금 누락을 탐지합니다(물론 나중에 완전히 양성이 감소함을 의미합니다).

그것을 사용하려면, 당신은valgrind --tool=helgrind, 이것이 그 매뉴얼입니다.또한 있습니다.valgrind --tool=drd(수동).헬그린드와 DRD는 서로 다른 모델을 사용하여 중복되는 버그를 감지할 수 있지만 서로 다를 수도 있습니다.오탐도 발생할 수 있습니다.

어쨌든 valgrind는 디버깅에 드는 수많은 시간을 절약했습니다(모든 시간은 아니지만 :).

스레드 프로그램을 디버깅할 때 놀라운 점 중 하나는 종종 버그 변경을 발견하거나 printf를 추가하거나 디버거(구어로는 Heisenbug)에서 프로그램을 실행할 때 사라지기도 한다는 것입니다.

스레드 프로그램에서 하이젠버그는 일반적으로 레이스 상태를 의미합니다.좋은 프로그래머는 순서에 의존적인 공유 변수나 자원을 찾을 것입니다.형편없는 프로그래머는 맹목적으로 잠꼬대로 그것을 고치려고 할 것입니다.

다중 스레드 응용 프로그램을 디버깅하기가 어렵습니다.*nix 환경에 적합한 GDB(옵션 DDD 프론트엔드 포함)나 윈도우에 Visual Studio와 함께 제공되는 디버거와 같은 좋은 디버거가 큰 도움이 될 것입니다.

'생각하기' 단계에서는 코딩을 시작하기 전에 상태 기계 개념을 사용합니다.그것은 디자인을 훨씬 더 선명하게 만들 수 있습니다.

printf's는 프로그램의 역동성을 이해하는 데 도움을 줄 수 있습니다.그러나 소스 코드를 어수선하게 만들기 때문에 매크로 DEBUG_OUT()을 사용하고 정의에서 부울 플래그로 활성화합니다.kill -USR1'을 통해 전송하는 신호로 이 플래그를 설정/지우는 것이 좋습니다. 타임스탬프가 있는 로그 파일로 출력을 보냅니다.

또한 assert (),을 사용하고 gdb와 ddd를 사용하여 코어 덤프를 분석하는 것을 고려합니다.

멀티 스레드 디버깅에 대한 접근 방식은 싱글 스레드와 비슷하지만, 일반적으로 사고 단계에서 더 많은 시간을 소비합니다.

  1. 무엇이 문제를 일으킬 수 있는지에 대한 이론을 개발합니다.

  2. 이론이 참일 경우 어떤 종류의 결과를 기대할 수 있는지 결정합니다.

  3. 필요한 경우 결과와 이론을 반증하거나 검증할 수 있는 코드를 추가합니다.

  4. 만약 당신의 이론이 사실이라면, 그 문제를 고치세요.

종종 이 이론을 증명하는 '실험'은 용의자 코드 주변에 중요한 섹션이나 뮤텍스를 추가하는 것입니다.그러면 중요한 부분을 체계적으로 축소해서 문제를 좁히도록 하겠습니다.중요한 섹션이 항상 최선의 해결책인 것은 아닙니다. 하지만 종종 빠른 해결책이 될 수도 있습니다.하지만 '스모킹 건'을 정확히 집어내는 데는 유용합니다.

말씀드린 것처럼 단일 스레드 디버깅에도 동일한 단계가 적용되지만 디버거에 들어가서 실행하는 것은 너무 쉽습니다.보통 디버거를 통해 실행되는 멀티 스레드 코드는 유용한 것을 얻지 못하기 때문에 멀티 스레드 디버깅은 코드에 대한 훨씬 더 강력한 이해를 필요로 합니다.

또한 헬그라인드는 훌륭한 도구입니다.인텔의 스레드 체커는 윈도우에서도 비슷한 기능을 수행하지만, 헬그라인드보다 훨씬 더 많은 비용이 듭니다.

저는 멀티 스레드, 고성능 세계에서만 발전하기 때문에 일반적으로 사용하는 방법은 다음과 같습니다.

설계 - 최적화가 더 나은 알고리즘입니다.

1) 당신의 함수를 논리적으로 분리할 수 있는 조각으로 나눕니다.이는 호출이 "A"를 수행하고 "A"만 수행하며 A 이후에는 B, C...를 수행하지 않음을 의미합니다.
2) 부작용 없음: 정적이든 아니든, 맨몸으로 글로벌 변수를 모두 제거합니다.부작용을 완전히 제거할 수 없는 경우 몇 군데에 격리(코드에 집중)합니다.
3) 가능한 한 많은 분리된 구성요소를 재진입합니다.이는 이들이 상태 비저장 상태임을 의미합니다. 이들은 모든 입력을 상수로 받아들이고 논리적으로 상수인 DECONED 파라미터만 조작하여 출력을 생성합니다.가능한 모든 곳에서 기준 대신 값을 전달합니다.
4) 상태가 있는 경우 상태 비저장 하위 어셈블리와 실제 상태 시스템 사이를 명확하게 구분합니다.이상적으로 상태 시스템은 단일 기능 또는 클래스로 상태 비저장 구성 요소를 조작합니다.

디버깅:

스레드 버그는 인종과 데드락의 두 가지 광범위한 맛으로 출시되는 경향이 있습니다.일반적으로 데드락은 훨씬 더 결정적입니다.

1) 데이터 손상이 있습니까?네 => 아마도 경주일 것입니다.
2) 버그는 실행될 때마다 발생합니까, 아니면 일부 실행에서만 발생합니까?YES => 교착 상태일 가능성이 높습니다(races은 일반적으로 비 determin적입니다).
3) 프로세스가 중단된 적이 있습니까?네 => 어딘가에 교착상태가 있습니다.가끔 걸려있는 것만 있다면 아마 경주도 경주가 있을 것입니다.

중단점은 논리적으로 유사하기 때문에 코드에서 동기화 프리미티브 자체와 매우 유사하게 작용하는 경우가 많습니다. 즉, 다른 컨텍스트(사용자)가 다시 시작하라는 신호를 보낼 때까지 현재 컨텍스트에서 실행을 강제로 중단시킵니다.즉, 코드에 있는 모든 중단점을 머프티 스레드 동작을 변경하는 것으로 봐야 하며, 중단점은 레이스 상태에 영향을 미치지만 (일반적으로) 데드락은 아닙니다.

원칙적으로 모든 중단점을 제거하고 버그 유형을 식별한 다음 이를 다시 도입하여 해결해야 합니다.그렇지 않으면, 그들은 단순히 더 많은 것들을 왜곡할 뿐입니다.

저는 브레이크 포인트를 많이 사용하는 편입니다.스레드 기능에 실제로 신경 쓰지 않고 부작용에 신경 쓴다면, 스레드가 종료되거나 루프 상태로 되돌아가기 직전 또는 대기 상태로 되돌아가기 직전에 해당 스레드를 확인할 수 있는 좋은 시간이 될 수 있습니다.

멀티스레드 프로그래밍을 시작했을 때..디버거 사용을 중단했습니다.저에게 핵심은 좋은 프로그램 분해와 캡슐화입니다.

모니터는 오류 없는 멀티 스레드 프로그래밍의 가장 쉬운 방법입니다.복잡한 잠금 의존성을 피할 수 없는 경우 프로그램이 중단될 때까지 기다렸다가 'pstack'을 사용하여 스택 트레이스를 확인하는 등 주기적인지 쉽게 확인할 수 있습니다.몇 가지 새로운 스레드와 비동기 통신 버퍼를 도입하여 순환 잠금을 해제할 수 있습니다.

주장을 사용하고 소프트웨어의 특정 구성 요소에 대해 단일 스레드 단위 테스트를 작성해야 합니다. 그런 다음 원하는 경우 디버거에서 실행할 수 있습니다.

언급URL : https://stackoverflow.com/questions/981011/c-programming-debugging-with-pthreads

반응형