책에서“컴파일러가 메모리에 변수를위한 공간을 할당합니다”라고 말하는 이유는 무엇입니까?


18

책에서 "컴파일러가 메모리에 변수를위한 공간을 할당합니다"라고 말하는 이유는 무엇입니까? 그것은 실행 파일 아닌가요? 예를 들어 다음 프로그램을 작성하면

#include <iostream>
using namespace std;

int main()
{
   int foo;
   return 0;
}

컴파일하고 실행 파일을 가져옵니다 (program.exe로 설정하십시오). program.exe를 실행하면이 실행 파일 자체가 변수 foo에 공간을 할당하라는 명령을 내립니다. 그렇지 않습니까? "컴파일러가이 작업을 수행합니다 ...


11
어떤 책에 대해 이야기하고 있습니까?
wirrbel

4
"관련 질문"은 별도의 질문이어야합니다.
SShaheen


컴파일러는이 작업을 수행하는 코드를 생성합니다. 직접 또는 간접적으로.
old_timer

참고로 stackoverflow.com/questions/7372024/… 컴파일러는 정렬을 위해 메모리에서 인식 된 변수의 위치를 ​​변경하기로 결정할 수 있습니다. 예 : stackoverflow.com/questions/17774276/…
NoChance

답변:


20

프로그램이 실제로 실행될 때 컴파일러가 사라진 것이 맞습니다. 그리고 다른 컴퓨터에서 실행되면 더 이상 컴파일러를 사용할 수 없습니다.

이것은 실제로 자신의 코드에 의해 할당 된 메모리를 명확하게 구별하는 것입니다. 컴파일러는 메모리 할당을 수행하는 일부 코드를 프로그램에 삽입합니다 (예 : new, malloc 또는 이와 유사한 명령 사용).

따라서 책은 컴파일러가 코드 파일에 명시 적으로 언급되지 않은 일부 코드를 추가했다고 말하기 위해 "컴파일러가이 작업을 수행합니다"를 사용합니다. 이것이 정확히 진행되고 있지 않다는 사실은 충분히 사실입니다. 이 관점에서, 튜토리얼에서 언급 된 많은 것들이 잘못되었지만 다소 정교한 설명이 필요할 것입니다.


네, 제가 믿었던 것입니다. 빠른 답변 감사합니다!
평화로운 코더

12
컴파일러는 컴파일 중에 스택 포인터에 대한 오프셋으로 변수를 대체하여 스택에 변수 foo를 할당합니다. mallocet에 의해 수행되는 힙 할당과 전혀 관련이 없습니다 . 알.
wirrbel

@holger : 당신의 반대는 물론 기술적으로 정확합니다. 그러나 스택 공간은 프로그램이 시작되기 전에 여전히 할당되어야합니다 (이는 CPU 아키텍처에 따라 다양한 방식으로 발생할 수 있음). 나는 이것이 어떻게 일어나는지 약간의 세부 사항을 찾으려고 노력했지만 성공하지 못했습니다.
thorsten müller

2
메인 스레드의 스택 크기는 링커에서 예약 한 다음 OS에서 처리한다고 생각합니다. 사용자 정의 스레드의 경우 힙 할당과 비슷합니다. 즉, 호출자가 런타임에 크기를 수정할 수 있습니다.
wirrbel

4

변수에 따라 다릅니다. OS는 힙을 할당하고, 프로그램은 스택을 할당하고, 컴파일러는 전역 / 정적 공간을 할당합니다. 즉, exe 자체에 내장되어 있습니다. 1MB의 전역 메모리를 할당하면 exe 크기가 1MB 이상 증가합니다.


1
그것은이 질문에 관한 것이 아닙니다.
Philipp

2
실제로 여기에 나열된 다른 답변보다 질문에 더 가깝습니다.
wirrbel

@ 제임스 아, 이것은 내 경험이 아닙니다. 예를 int test[256][1024]; int main(){ test[0][0]=2; return 0; } 들어이 작은 프로그램에는 1MB가 할당되었지만 1.4Kb 객체 파일과 8.4Kb 실행 파일 만 생성됩니다. 그래도 올바른 양의 RAM을 사용해야합니다.
Garet Claborn

1
전역을 위해 저장된 할당 명령이 아닌가? int 또는 char와 같은 프리미티브를 사용하여 모든 값을 하드 코딩 한 경우 실행 파일의 크기는 추가 된 변수의 양보다 확실히 증가합니다. 와 같은 int a1=1,a2=2,... 모든 방법으로 ... , a1048576=1048576;그때 당신은 확실히 1mb보다 큰 무언가를 얻을 것이라고 생각합니다.
Garet Claborn

2
그것은 exe의 BSS 섹션에 데이터를 넣는 모든 것
James

4

컴파일러 가하는 일은 코드를 가져 와서 머신 코드로 컴파일하는 것입니다. 언급 한 것은 컴파일러가 번역 해야하는 좋은 예입니다.

예를 들어 쓸 때

int foo;

'컴파일러가 생성하는 출력 에서 컴퓨터가 나중에 참조 할 수있는 int에 충분한 RAM을 예약하도록 요청하는 것으로 볼 수 있습니다. 컴파일러는 아마도 리소스 ID 또는 일부 메커니즘을 사용하여 foo를 추적합니다. 기계어 코드에서는 어셈블리를 작성하는 대신 텍스트 파일에서 foo를 사용하게됩니다! 만세 !

따라서 컴파일러가 모든 대상 프로세서 및 장치에 편지 ( 또는 소설 / 백과 사전 )를 쓰고 있기 때문에 이것을 볼 수도 있습니다 . 문자는 이진 신호로 작성되며, 일반적으로 대상을 변경하여 다른 프로세서로 변환 될 수 있습니다. '문자'및 / 또는 콤보는 모든 종류의 요청 및 / 또는 데이터를 보낼 수 있습니다. 프로그래머가 사용한이 변수에 대한 공간을 할당하십시오.


3

"컴파일러가 메모리를 할당한다"고 말하는 것은 문자 그대로 의미가 정확하지 않을 수도 있지만 올바른 방식으로 암시하는 은유입니다.

실제로 일어나는 일은 컴파일러가 자체 메모리를 할당하는 프로그램을 만드는 것입니다. 메모리를 할당하는 프로그램이 아니라 OS입니다.

따라서 실제로 발생하는 것은 컴파일러가 메모리 요구 사항을 설명하는 프로그램을 만들고 OS에서 해당 설명을 사용하여 메모리를 할당하는 것입니다. OS가 프로그램이고 프로그램이 실제로 아무것도하지 않는 것을 제외하고는 CPU에 의해 수행되는 계산을 설명합니다. CPU가 실제로 복잡한 전자 회로라는 것을 제외하고는 인위적으로 작은 동형이 아닙니다.

그러나 프로그램과 컴파일러, CPU를 컴퓨터 안에 사는 작은 사람들이라고 생각하는 것이 합리적입니다. 왜냐하면 실제로 있기 때문이 아니라 인간의 뇌에 잘 맞는 은유이기 때문입니다.

일부 은유는 한 수준의 추상화에서는 사물을 설명하는 데 효과적이지만 다른 수준에서는 효과가 없습니다. 컴파일러 수준을 생각하면 컴파일되는 프로그램이 실제로 "할당 메모리"로 실행될 때 메모리가 할당되는 코드 생성 동작을 설명하는 것이 합리적입니다. 컴파일러의 작동 방식에 대해 생각할 때 올바른 아이디어를 얻었으므로 우리가하고있는 일을 잊어 버릴 정도로 오래 걸리지 않았습니다. 컴파일 된 프로그램의 실행 수준에서이 비유를 사용하려고하면 이상한 방식으로 오해의 소지가 있습니다.


0

변수를 저장할 위치를 결정하는 컴파일러입니다. 스택 또는 자유 레지스터에있을 수 있습니다. 컴파일러가 만든 스토리지 결정에 관계없이 해당 변수에 액세스하는 해당 머신 코드가 생성되며 런타임시 변경할 수 없습니다. 이런 의미에서 컴파일러는 변수를위한 공간 할당을 담당하고 최종 program.exe는 맹목적으로 런타임에서 좀비처럼 행동합니다.

이제 malloc과 같은 다른 동적 메모리 관리와 혼동하지 마십시오. 새로운 메모리 관리 또는 자체 메모리 관리 일 수 있습니다. 컴파일러는 가변 스토리지 및 액세스를 처리하지만 다른 프레임 워크 / 라이브러리에서 실제 값이 무엇을 의미하는지는 중요하지 않습니다. 예를 들면 다음과 같습니다.

byte* pointer = (byte*)malloc(...);

런타임에 malloc은 임의의 숫자를 리턴 할 수 있지만 컴파일러는 신경 쓰지 않으며, 그 숫자를 저장할 위치 만 신경 쓰면됩니다.


0

보다 정확한 문구는 다음과 같습니다 .- "컴파일러가 변수를위한 공간을 예약하도록 로더에 지시합니다."

C-ish 환경에는 변수를위한 세 가지 유형의 공간이 있습니다.

  • 정적 변수에 대한 고정 블록
  • "자동"변수에 대한 큰 블록은 일반적으로 "스택"이라고합니다. 함수는 진입시 청크를 잡고 리턴시 해제합니다.
  • malloc () 또는 유사한 메모리 관리 API를 사용하여 프로그램 관리 메모리가 할당되는 "힙"이라는 큰 블록입니다.

최신 OS 힙 메모리는 실제로 예약되지 않지만 필요에 따라 할당됩니다.


0

그렇습니다.이 경우 (함수에 변수 선언) 책의 문장이 잘못되었을 수 있습니다. 함수에서 변수를 선언하면 함수에 들어갈 때 스택에 할당됩니다. 어쨌든, 컴파일러는 상황을 최적화해야합니다. 함수가 비 재귀 적이라면 ( main()좋은 후보입니다), 컴파일 타임 (BSS에서)을 "할당"하는 것이 좋습니다.

(변수가 어디에 있는지 궁금하다면, 더러운 방법을 확인할 수 있습니다 (어쨌든 obj 파일 구조를 검사하지 않으려는 경우 왜 그렇지 않습니까?) 정적, 동적,- malloc()할당 등의 주소를 표시하고 ( 가독성을 높이기 위해 %X포맷터 사용 printf()) 스택에있는 변수는 메모리 주소가 매우 다릅니다.


0

런타임에 수행되는 유일한 작업은 스택 포인터를 일정량 충돌시키는 것입니다. 따라서 컴파일러는 미리 결정합니다.

  • 함수에 필요한 스택 공간
  • 스택 포인터로부터 어떤 오프셋에 모든 개별 변수가 위치합니다.

이것은 "할당"이라고 할 수 있지만, 물론 컴파일 타임에는 컴파일러가 실행중인 프로그램의 모델에만 배치됩니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.