BackTrace ()를 사용하는 것보다 통화 스택의 깊이를 찾는 저렴한 방법이 있습니까?

StackOverflow https://stackoverflow.com/questions/582673

  •  06-09-2019
  •  | 
  •  

문제

내 로깅 코드는 반환 값을 사용합니다 백트레이스 () 현재 스택 깊이를 결정하려면 (예쁜 인쇄 목적으로) 프로파일 링에서 이것이 꽤 비싼 전화임을 알 수 있습니다.

더 저렴한 방법이 있다고 생각하지 않습니까? 프레임 주소는 신경 쓰지 않고 그 중 몇 개가 있는지 신경 쓰지 않습니다.

편집 : 이러한 로깅 기능은 대형 코드 기반 전체에 사용되므로 스택 깊이를 수동으로 추적하는 것이 실제로 옵션이 아닙니다.

도움이 되었습니까?

해결책

스택을 스스로 걷는 것은 매우 빠릅니다. backtrace() 기호 이름을 찾는 것입니다. x86에서는 다음을 수행 할 수 있습니다.

inline uint32_t get_ebp(void)
{
    __asm__ __volatile__("mov %%ebp, %%eax");
}

int get_stack_depth(void)
{
    uint32_t ebp = get_ebp();
    int stack_depth = 0;
    while(ebp != 0)
    {
        ebp = *(uint32_t *)ebp;
        stack_depth++;
    }
    return stack_depth;
}

이것은 사슬을 걸을 것입니다 ebp 포인터. 이것은 극도로 포트가 불가능하다는 것을 명심하십시오. 또한 이것은 인쇄되거나 꼬리를 최적화 한 기능을 계산하지 않을 것입니다 (물론, 물론, backtrace() 같은 문제가 있습니다).

또 다른 중요한 문제는 종료 조건입니다. main(), 종종 스택에서 찾을 수있는 것에 대해 보장되지 않습니다. 따라서 LIBC가 Null 프레임 포인터를 넣지 않으면 Segfault 일 가능성이 높습니다. 끝에서 종료 값을 볼 수 있습니다. main().

다른 팁

꽤 인쇄 된 기능이 합리적으로 포함 된 경우, 계약 (또는 들여 쓰기 크기)을 매개 변수로 전달하고 다른 디스플레이 기능을 호출 할 때 증가하십시오.

당신은 그냥 가지고 다닐 수 없어요 TLS 당신과 함께 "깊이"라고 불렀고 모든 기능을 증가 / 감소시킬 수 있습니까? 스택을 더 빨리 걸어 가기 위해 자신의 코드를 작성할 수 있지만, 변수를 주위에 가지고 다니는 것보다 여전히 느리게 진행됩니다.

ARM 아키텍처 용 :

register unsigned long *rfp asm("fp");
unsigned long *fp = rfp;
unsigned long depth = 0;

while(fp)
{
    fp = (unsigned long *)(*(fp -3));
    depth++;
}

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