programing

컴파일 시 스택 사용량 확인

yellowcard 2023. 10. 27. 21:50
반응형

컴파일 시 스택 사용량 확인

C에서 컴파일 시간에 함수가 필요로 하는 스택 크기를 알고 출력할 수 있는 방법이 있습니까? 여기 제가 알고 싶은 것은 다음과 같습니다.

몇 가지 기능을 사용해 보겠습니다.

void foo(int a) {
    char c[5];
    char * s;
    //do something
    return;
}

이 함수를 컴파일할 때 호출할 때 스택 공간을 얼마나 소모하는지 알고 싶습니다.이것은 큰 버퍼를 숨기는 구조의 온스택 선언을 탐지하는 데 유용할 수 있습니다.

다음과 같은 것을 인쇄할 수 있는 것을 찾고 있습니다.

: 은 file fo.c : function fo stack n바이트들

생성된 어셈블리를 보지 않고 그것을 알 수 있는 방법이 있습니까? 또는 컴파일러에 대해 설정할 수 있는 제한이 있습니까?

업데이트 : 주어진 프로세스에 대해 런타임 스택 오버플로를 방지하려는 것이 아니라 컴파일러가 결정한 함수 스택 사용이 컴파일 프로세스의 출력으로 사용 가능한 경우 런타임 전에 찾을 수 있는 방법을 찾고 있습니다.

다른 말로 하자면, 함수에 로컬인 모든 객체의 크기를 알 수 있을까요? 컴파일러 최적화는 내 친구가 아닐 것입니다. 왜냐하면 몇몇 변수는 사라지지만 상한은 괜찮기 때문입니다.

리눅스 커널 코드는 x86의 4K 스택에서 실행됩니다.그래서 그들은 신경을 씁니다.이를 확인하기 위해 사용하는 것은 자신들이 작성한 펄 스크립트이며, 최근 커널 타르볼(2.6.25가 이를 가지고 있음)에서 스크립트/checkstack.pl 로 찾을 수 있습니다.objdump의 출력으로 실행되며 사용 설명서는 첫 번째 주석에 있습니다.

사용자 공간 바이너리에 이미 오래전에 사용했던 것 같은데 펄 프로그래밍을 조금만 알고 계시면 고장나면 고치기 쉽습니다.

어쨌든 기본적으로 GCC의 산출물을 자동으로 보는 것입니다.그리고 커널 해커들이 그런 툴을 작성했다는 것은 GCC로 그것을 할 수 있는 정적인 방법이 없다는 것을 의미합니다(혹은 그것이 아주 최근에 추가되었을 수도 있지만, 나는 그렇게 생각하지 않습니다).

그건 그렇고, mingw 프로젝트의 objdump와 ActivePerl, 또는 Cygwin을 사용하면 윈도우와 다른 컴파일러로 얻은 바이너리에서도 그렇게 할 수 있을 것입니다.

StackAnyser는 실행 코드 자체와 디버깅 정보를 조사하는 것 같습니다.이 답변에 의해 설명된 것은 제가 찾고 있는 것입니다. 스택 분석기는 저에게 오버킬로 보입니다.

ADA를 위해 존재하는 것과 유사한 것이 좋습니다.gnat 매뉴얼의 이 매뉴얼 페이지를 보십시오.

22.2 정적 스택 사용량 분석

-fstack-usage로 컴파일된 장치는 기능별로 사용된 스택의 최대 양을 지정하는 추가 파일을 생성합니다.파일의 기본 이름은 .su 확장자가 있는 대상 개체 파일과 동일합니다.이 파일의 각 줄은 세 개의 필드로 구성됩니다.

* The name of the function.
* A number of bytes.
* One or more qualifiers: static, dynamic, bounded. 

두 번째 필드는 함수 프레임의 알려진 부분의 크기에 해당합니다.

한정자 정적은 함수 프레임 크기가 순수하게 정적임을 의미합니다.이는 일반적으로 모든 지역 변수가 정적 크기를 가짐을 의미합니다.이 경우 두 번째 필드는 함수 스택 활용도의 신뢰할 수 있는 척도입니다.

한정자 동적은 함수 프레임 크기가 정적이 아님을 의미합니다.이는 주로 일부 지역 변수가 동적 크기를 가질 때 발생합니다.이 한정자가 단독으로 나타나는 경우 두 번째 필드는 함수 스택 분석의 신뢰할 만한 측도가 아닙니다.제한된 필드로 자격을 갖추면 두 번째 필드가 함수 스택 활용도의 신뢰할 수 있는 최대치임을 의미합니다.

정적 코드 분석이 이에 대한 충분한 수치를 제공하지 못하는 이유를 모르겠습니다.

임의의 주어진 함수에서 모든 지역 변수를 찾는 것은 사소한 일이며, 각 변수에 대한 크기는 C 표준(빌트 인 유형의 경우) 또는 계산(구조 및 조합과 같은 복잡한 유형의 경우)을 통해 구할 수 있습니다.

물론, 컴파일러는 패딩, 레지스터에 변수를 넣거나 불필요한 변수를 완전히 제거하는 등 다양한 최적화 작업을 수행할 수 있기 때문에 100% 정확하다고 보장할 수는 없습니다.그러나 그것이 주는 어떤 대답이라도 최소한 좋은 추정이 되어야 합니다.

구글 검색을 빠르게 해서 StackAnalyzer를 찾았는데 다른 static code 분석 도구들도 비슷한 기능을 가지고 있는 것 같습니다.

만약 당신이 100% 정확한 수치를 원한다면, 당신은 컴파일러의 출력을 보거나 Ralph가 그의 답장에서 제안한 것처럼 실행시간 동안 그것을 확인해야 할 것입니다.

당신의 모든 것을 정리하는 사람이기 때문에 컴파일러만이 정말로 알 것입니다.생성된 어셈블리를 보고 프리앰블에 얼마나 많은 공간이 예약되어 있는지 확인해야 할 것입니다. 그러나 그것은 실제로 다음과 같은 것들을 설명하지 않습니다.alloca그들은 실행시간에 그들의 일을 합니다.

여러분이 임베디드 플랫폼에 있다고 가정할 때, 여러분은 툴체인이 이것을 시도하고 있다는 것을 발견할 수 있을 것입니다.우수한 상용 임베디드 컴파일러(예: Arm/Keil 컴파일러)는 스택 사용에 대한 보고서를 생성하는 경우가 많습니다.

물론 인터럽트와 재귀는 일반적으로 그 범위를 약간 넘어선 것이지만, 어떤 사람이 스택 어딘가에 있는 수 메가바이트의 버퍼를 가지고 심각한 실수를 저질렀는지 대략적으로 알 수 있습니다.

정확히 "컴파일 시간"은 아니지만, 빌드 후 단계로 수행합니다.

  • 링커가 당신을 위해 지도 파일을 만들도록 합니다.
  • 지도 파일의 각 기능에 대해 실행 파일의 해당 부분을 읽고 기능 프롤로그를 분석합니다.

Stack Analyzer와 비슷하지만 훨씬 간단합니다.나는 실행 파일이나 해체를 분석하는 것이 컴파일러 출력을 얻을 수 있는 가장 쉬운 방법이라고 생각합니다.컴파일러가 내부적으로 알고 있기는 하지만 이를 통해 얻을 수 없을 것 같습니다(컴파일러 벤더에게 기능 구현을 요청하거나 오픈 소스 컴파일러를 사용하는 경우 직접 수행하거나 누군가가 대신 수행하도록 요청할 수도 있습니다).

이를 구현하려면 다음 작업이 필요합니다.

  • 지도 파일을 파싱할 수 있는
  • 실행 파일 형식 이해
  • 기능 프롤로그가 어떤 모습인지 알고 그것을 "decode"할 수 있습니다.

목표 플랫폼에 따라 이 작업이 얼마나 쉽거나 어려울지가 달라집니다. (내장되어 있습니까?어떤 CPU 아키텍처?무슨 컴파일러?)

이 모든 작업은 x86/Win32에서 수행할 수 있습니다. 하지만 이런 작업을 전혀 수행하지 않고 처음부터 이 모든 작업을 수행해야 한다면 작업이 완료되고 작업이 완료되기까지 며칠이 걸릴 수 있습니다.

일반적으로 그렇지 않습니다.이론 컴퓨터 과학의 문제 중지는 일반 프로그램이 주어진 입력에 대해 중단되는지 여부를 예측할 수조차 없다는 것을 암시합니다.일반적으로 프로그램 실행에 사용되는 스택을 계산하는 것은 훨씬 더 복잡할 것입니다.그래서 안 돼요.아마 특별한 경우일 겁니다.

임의 길이의 입력에 따라 재귀 수준이 달라지며 이미 운이 없다고 가정해 보겠습니다.

언급URL : https://stackoverflow.com/questions/126036/checking-stack-usage-at-compile-time

반응형