2011-12-09 4 views
5

가능한 한 빨리 호출 스택을 캡처하려고합니다. 지금이 내가있어 무엇 :호출 스택을 빠르게 캡처하십시오.

이 메모리 추적 시스템에 사용하기위한 것입니다, 그래서 나는 그들이 나중에 할 수있는 경우 (일부 사용자 중심의 이벤트에 따라 주소의 배열로 끝날 것을 완벽하게 괜찮
void* addrs[10] = {}; 
DWORD hash; 
RtlCaptureStackBackTrace(0, 10, addrs, &hash); 

for(size_t i = 0; i <10; ++i) 
{ 
    std::cout << addrs[i] << '\n'; 
} 

) 인간이 읽을 수있는 무언가로 바뀌십시오.

  • addrs을 사람이 읽을 수있는 것으로 변환하려면 어떻게해야합니까?
  • RtlCaptureStackBackTrace보다 더 빨리 있나요 (아래 편집 참조)?
  • 호출 스택을 캡처하는 데 교차 플랫폼 방식이 있습니까?

편집 :

내가 SymFromAddrSymGetLineFromAddr64를 사용하여 사람이 읽을 수있는 정보로 주소를 돌았 다. 그러나, 내 버전 newCaptureStackBackTrace을 사용하면 원본보다 30 배 오래 걸리고 거의 모든 시간이 스택 추적으로 인해 발생합니다. 나는 여전히 더 빠른 해결책을 찾고있다!

답변

2

호출 스택을 캡처하는 크로스 플랫폼 방법이 있습니까?

빠른 대답은 불행히도 그것은 불가능이다. 서로 다른 컴파일러와 플랫폼은 스택을 다르게 구성 할 것이고 컴파일러의 "도움"없이도 스택을 정확히 추적 할 수는 없을 것입니다. 스택을 사용하는 플랫폼에서 할 수있는 대부분의 작업 - 프레임 기본 포인터는 EBP 또는 RBP의 값을 사용하여 스택을 위로 이동하는 것이고 심지어 32 비트 x86 실행 파일 또는 x86_64 실행 파일을 실행 중인지 여부에 따라 다릅니다. 또한 UNIX 응용 프로그램 -Binary-interface (ABI)와 Windows ABI를 관리하는 규칙은 완전히 다릅니다.

  1. 유닉스 32 비트 ABI
  2. 유닉스 64 비트 ABI
  3. Windows 32 비트 ABI
  4. : 그래서 일반적으로, 당신은 적어도 네 가지 가능성을 지원하는 데 끝날거야 Windows 64 비트 ABI

UNIX 64 비트 ABI는 컴파일러가 스택 프레임 기본 포인터를 지원할지 여부를 선택할 수 있도록합니다. 포인터가 보장되지 않습니다. 컴파일러는 단순히 별도의 기본 포인터를 사용하지 않고 스택 포인터 자체에 대해 모든 스택 변수를 참조하도록 선택할 수 있습니다. 이는 여전히 UNIX 64 비트 ABI와 호환되는 것으로 간주됩니다.

그래서 당신이 볼 수 있듯이, 모든 가능한 변형으로, 당신은 매우 힘든 시간을 신뢰할 수있는 크로스 플랫폼 스택 추적을 만드는이 될 것입니다. 타겟팅하는 플랫폼에서 사용할 수있는 도구를 사용하는 것이 가장 좋습니다. 여러 플랫폼을 지원해야하는 경우 불행히도 스택 추적을 안정적으로 수행하는 데 도움이되는 플랫폼 별 도구를 사용하면 코드 중복이 발생합니다.

0

크로스 플랫폼 방식은 없지만 트릭을 수행하는 크로스 플랫폼 라이브러리가 있습니다. It's a common requirement for garbage collectors.

불행히도 이러한 라이브러리를 권장하기에는 불충분합니다. MMgc에는 임베디드가 포함되어 있습니다 (위 링크에서 설명 됨). Hans Boehm의 쓰레기 수거통에는 다른 것들이 있습니다.

이러한 라이브러리는 일반적으로 Windows의 RtlCaptureStackBacktrace과 같은 플랫폼 관련 호출에 의존합니다. 그러한 라이브러리가 플랫폼 별 호출보다 빠르면 나는 놀랄 것이다. 그러나 그러한 라이브러리가 현저하게 느려지는 경우 나는 또한 놀랄 것이다. Windows API 호출을 직접 호출할지 또는 해당 호출을 다른 라이브러리를 통해 라우팅 할지를 선택하는 것이 유일한 질문입니다.

관련 문제