답변:
스택 프레임은 스택으로 푸시되는 데이터 프레임입니다. 호출 스택의 경우 스택 프레임은 함수 호출 및 해당 인수 데이터를 나타냅니다.
올바르게 기억하면 함수 반환 주소가 먼저 스택으로 푸시 된 다음 로컬 변수의 인수와 공간이 푸시됩니다. 아키텍처에 따라 다르지만 함께 "프레임"을 만듭니다. 프로세서는 각 프레임에 몇 바이트가 있는지 알고 있으며 프레임이 스택에서 밀리고 튀어 나옴에 따라 스택 포인터를 이동시킵니다.
높은 수준의 호출 스택과 프로세서의 호출 스택에는 큰 차이가 있습니다.
프로세서의 호출 스택에 대해 이야기 할 때 어셈블리 또는 머신 코드에서 바이트 / 워드 수준 의 주소와 값을 다루는 것에 대해 이야기하고 있습니다. 고급 언어에 대해 이야기 할 때 "호출 스택"이 있지만 런타임 환경에서 관리하는 디버깅 / 런타임 도구이므로 프로그램에 문제가 발생한 것을 높은 수준으로 기록 할 수 있습니다. 이 수준에서 줄 번호, 메소드 및 클래스 이름과 같은 것이 종종 알려져 있습니다. 프로세서가 코드를 가져올 때까지는 이러한 개념이 전혀 없습니다.
스택을 잘 이해하면 프로그램에서 메모리가 작동하는 방식을 이해하고 프로그램에서 메모리가 작동하는 방식을 이해하면 프로그램에서 함수가 저장되는 방식을 이해하고 프로그램에서 함수가 저장되는 방식을 이해하면 재귀 함수가 작동하는 방식을 이해할 수 있습니다. 재귀 함수의 작동 방식을 이해하면 컴파일러의 작동 방식을 이해하고 컴파일러의 작동 방식을 이해하면 마음이 컴파일러로 작동하며 프로그램을 매우 쉽게 디버깅합니다.
스택 작동 방식을 설명하겠습니다.
먼저 함수가 스택에서 어떻게 표현되는지 알아야합니다.
힙은 동적으로 할당 된 값을 저장합니다.
스택은 자동 할당 및 삭제 값을 저장합니다.
예제로 이해하자 :
def hello(x):
if x==1:
return "op"
else:
u=1
e=12
s=hello(x-1)
e+=1
print(s)
print(x)
u+=1
return e
hello(4)
이제이 프로그램의 일부를 이해하십시오.
이제 스택이 무엇이고 스택 부분이 무엇인지 살펴 보겠습니다.
스택 할당 :
함수의 반환 조건이 충족되면 로컬 변수를로드했는지 여부에 관계없이 스택 프레임을 사용하여 스택에서 즉시 반환됩니다. 이것은 재귀 함수가 기본 조건을 만족시키고 기본 조건 이후에 리턴 할 때마다 기본 조건이 프로그램의 "else"부분에있는 로컬 변수를로드하기를 기다리지 않음을 의미합니다. 다음 프레임이 활성화 레코드에있는 스택에서 현재 프레임을 즉시 반환합니다.
실제로 이것을보십시오 :
블록의 할당 해제 :
따라서 함수가 return 문을 만나면 스택에서 현재 프레임을 삭제합니다.
스택에서 반환되는 동안 값은 스택에 할당 된 원래 순서와 반대로 반환됩니다.
hello()
에는 재귀 적으로 호출 hello()
된 재귀 적으로 호출 된 3 개의 스택 프레임 이 있으며 hello()
전역 프레임은 첫 번째 hello()
?
빠른 마무리. 어쩌면 누군가 더 나은 설명이있을 수 있습니다.
호출 스택은 하나 또는 여러 개의 스택 프레임으로 구성됩니다. 각 스택 프레임은 아직 리턴으로 종료되지 않은 함수 또는 프로 시저에 대한 호출에 해당합니다.
스택 프레임을 사용하기 위해 스레드는 두 개의 포인터를 유지합니다. 하나는 스택 포인터 (SP), 다른 하나는 프레임 포인터 (FP)입니다. SP는 항상 스택의 "맨 위"를 가리키고 FP는 항상 프레임의 "맨 위"를 가리 킵니다. 또한 스레드는 다음에 실행될 명령을 가리키는 프로그램 카운터 (PC)를 유지 관리합니다.
다음은 스택에 저장됩니다. 로컬 변수 및 임시, 현재 명령어의 실제 매개 변수 (프로 시저, 함수 등)
스택 청소와 관련하여 서로 다른 호출 규칙이 있습니다.
"콜 스택은 스택 프레임으로 구성되어 있습니다 ..."— Wikipedia
스택 프레임은 스택에 넣는 것입니다. 호출 할 서브 루틴에 대한 정보를 포함하는 데이터 구조입니다.
프로그래머는 스택 프레임에 대해 광범위한 용어 (단 하나의 함수 호출 만 제공하고 리턴 주소, 인수 및 로컬 변수를 유지하는 스택의 단일 엔티티)가 아니라 좁은 의미로 질문에 대해 stack frames
언급 할 수 있습니다. 컴파일러 옵션의 컨텍스트.
질문의 저자가 의미했는지 여부에 관계없이 컴파일러 옵션의 측면에서 스택 프레임 개념은 매우 중요한 문제이며 다른 답변에서는 다루지 않습니다.
예를 들어, Microsoft Visual Studio 2015 C / C ++ 컴파일러에는 다음과 관련된 옵션이 있습니다 stack frames
.
GCC에는 다음이 있습니다.
인텔 C ++ 컴파일러에는 다음이 있습니다.
다음과 같은 별칭이 있습니다.
델파이에는 다음과 같은 명령 행 옵션이 있습니다.
컴파일러의 관점에서 볼 때 스택 프레임은 루틴 의 시작 및 종료 코드 일 뿐이며 앵커를 스택으로 푸시합니다. 디버깅 및 예외 처리에도 사용할 수 있습니다. 디버깅 도구는 스택에 위치하는 동안 스택 데이터를 스캔하고 이러한 앵커를 사용하여 백 트레이싱 call sites
할 수 있습니다. 즉, 함수 이름을 계층 적으로 호출 된 순서대로 표시합니다. 인텔 아키텍처의 경우,은 push ebp; mov ebp, esp
또는 enter
항목 및 mov esp, ebp; pop ebp
또는 leave
출구를.
그렇기 때문에 컴파일러는 컴파일러 옵션과 관련하여 스택 프레임의 내용을 이해하는 것이 매우 중요합니다. 컴파일러는이 코드를 생성할지 여부를 제어 할 수 있기 때문입니다.
경우에 따라 스택 프레임 (루틴에 대한 입력 및 종료 코드)을 컴파일러에서 생략 할 수 있으며 변수는 편리한 기본 포인터 (BP / ESP / RSP). 스택 프레임 생략 조건 : 예 :
스택 프레임 (루틴의 입력 및 종료 코드)을 생략하면 코드가 더 작고 빨라질 수 있지만, 스택의 데이터를 역 추적하고 프로그래머에게 표시하는 디버거의 기능에 부정적인 영향을 줄 수도 있습니다. 다음은 함수가 시작 및 종료 코드를 가져야하는 조건을 결정하는 컴파일러 옵션입니다. 예를 들어 (a) 항상, (b) 절대, (c) 필요할 때 (조건 지정).
스택 프레임은 함수 호출과 관련된 압축 정보입니다. 이 정보에는 일반적으로 함수에 전달 된 인수, 지역 변수 및 종료시 반환되는 위치가 포함됩니다. 활성화 레코드는 스택 프레임의 다른 이름입니다. 스택 프레임의 레이아웃은 제조업체에 의해 ABI에서 결정되며 ISA를 지원하는 모든 컴파일러는이 표준을 준수해야하지만 레이아웃 체계는 컴파일러에 따라 달라질 수 있습니다. 일반적으로 스택 프레임 크기는 제한되지 않지만 스택 프레임을 방해하지 않고 시스템 호출 등을 실행할 수 있도록 "빨간색 / 보호 영역"이라는 개념이 있습니다.
SP는 항상 있지만 일부 ABI (예 : ARM 및 PowerPC)에는 FP가 선택 사항입니다. 스택에 배치해야하는 인수는 SP 만 사용하여 오프셋 할 수 있습니다. 함수 호출을 위해 스택 프레임이 생성되는지 여부는 인수의 유형 및 개수, 지역 변수 및 지역 변수에 일반적으로 액세스하는 방법에 따라 다릅니다. 대부분의 ISA에서는 먼저 레지스터가 사용되며 인수 전달 전용 레지스터보다 많은 인수가있는 경우 스택에 배치됩니다 (예 : x86 ABI에는 정수 인수를 전달하는 6 개의 레지스터가 있습니다). 따라서 때때로 일부 함수는 스택에 스택 프레임을 배치 할 필요가 없으며 반환 주소 만 스택에 푸시됩니다.