programing

변수 이름은 C의 메모리에 어떻게 저장됩니까?

copyandpastes 2022. 7. 4. 23:49
반응형

변수 이름은 C의 메모리에 어떻게 저장됩니까?

C에 다음과 같은 변수가 있다고 가정합니다.variable_name예를 들어 다음 위치에 있다고 칩니다.0xaaaaaaaa그 메모리 주소에는, 123 의 정수가 있습니다.다른 말로 하자면variable_name에는 123이 포함되어 있습니다.

"라는 표현에 대한 해명을 구하고 있습니다.variable_name설치 장소:0xaaaaaaaa". 컴파일러는 문자열 "variable_name"이 특정 메모리 주소와 관련되어 있음을 어떻게 인식합니까?문자열 "variable_name"이 메모리 어딘가에 저장되어 있습니까?컴파일러는 단지 다음 명령어를 대체합니까?variable_name위해서0xaaaaaaaa그걸 볼 때마다, 만약 볼 수 있다면, 그걸 대체하기 위해서 기억을 사용해야 하지 않을까요?

컴파일러 실행 후 변수 이름은 더 이상 존재하지 않습니다(공유 라이브러리에서 내보낸 글로벌이나 디버깅 기호와 같은 특수한 경우는 제외).컴파일 전체의 목적은 소스 코드로 나타나는 심볼 이름과 알고리즘을 네이티브 머신 명령으로 변환하는 것입니다.네, 만약 당신이 글로벌하게variable_name컴파일러와 링커는 이 파일을 다음 위치에 배치합니다.0xaaaaaaaa코드 내에서 사용되는 모든 위치에 해당 주소를 통해 액세스할 수 있습니다.

문자 그대로의 질문에 답하려면:

컴파일러는 문자열 "variable_name"이 특정 메모리 주소와 관련되어 있음을 어떻게 인식합니까?

툴 체인(컴파일러와 링커)은 함께 동작하여 변수의 메모리 위치를 할당합니다.모든 참조를 추적하는 것은 컴파일러의 역할이며 링커는 나중에 올바른 주소를 입력합니다.

문자열입니까?"variable_name"기억 속 어딘가에 저장돼 있을까?

컴파일러가 실행되고 있는 동안만.

컴파일러는 단지 다음 명령어를 대체합니까?variable_name위해서0xaaaaaaaa그걸 볼 때마다, 만약 볼 수 있다면, 그걸 대체하기 위해서 기억을 사용해야 하지 않을까요?

네, 거의 그런 일이 벌어지죠 링커와 함께 하는 2단계 작업이라는 것만 빼면요네, 메모리를 사용하지만 컴파일러의 메모리이지 실행 시 프로그램에는 아무것도 없습니다.

예를 들면 이해에 도움이 될 수 있습니다.이 프로그램을 사용해 보겠습니다.

int x = 12;

int main(void)
{
    return x;
}

꽤 간단하죠?이 프로그램을 컴파일하여 디스어셈블리를 살펴보겠습니다.

$ cc -Wall -Werror -Wextra -O3    example.c   -o example
$ otool -tV example
example:
(__TEXT,__text) section
_main:
0000000100000f60    pushq   %rbp
0000000100000f61    movq    %rsp,%rbp
0000000100000f64    movl    0x00000096(%rip),%eax
0000000100000f6a    popq    %rbp
0000000100000f6b    ret

저것 좀 봐주세요movl라인이요? 글로벌 변수를 잡고 있습니다(이 경우 명령 포인터의 상대적인 방식으로).에 대해서는 더 이상 언급하지 않는다.x.

이제 좀 더 복잡하게 로컬 변수를 추가해 보겠습니다.

int x = 12;

int main(void)
{  
    volatile int y = 4;
    return x + y;
}

이 프로그램의 분해는 다음과 같습니다.

(__TEXT,__text) section
_main:
0000000100000f60    pushq   %rbp
0000000100000f61    movq    %rsp,%rbp
0000000100000f64    movl    $0x00000004,0xfc(%rbp)
0000000100000f6b    movl    0x0000008f(%rip),%eax
0000000100000f71    addl    0xfc(%rbp),%eax
0000000100000f74    popq    %rbp
0000000100000f75    ret

이제 두 개가 있다movl설명서와addl설명.보시는 것처럼 첫 번째는movl초기화 중y스택(베이스 포인터 - 4)에 배치됩니다.그럼 다음번에는movl글로벌화x등록부에.eax, 및addl추가하다y그 값까지.하지만 보다시피, 문자 그대로는x그리고.y끈은 더 이상 존재하지 않아요프로그래머인 당신에게 편리했던 것들이지만, 컴퓨터는 실행 시 전혀 신경 쓰지 않습니다.

모든 변수는 컴파일러에 의해 대체됩니다.처음에 참조로 대체되고 나중에 링커는 참조 대신 주소를 배치합니다.

바꿔 말하면.컴파일러가 실행되자마자 변수 이름을 사용할 수 없습니다.

C 컴파일러는 먼저 변수 이름과 변수 이름이 메모리에 있는 위치 사이의 관계를 저장하는 기호 테이블을 만듭니다.컴파일 시 이 테이블을 사용하여 다른 사용자가 설명한 바와 같이 변수의 모든 인스턴스를 특정 메모리 위치로 바꿉니다.위키피디아 페이지에서 더 많은 것을 찾을 수 있습니다.

를 구현 상세라고 합니다.제가 지금까지 사용해 본 컴파일러는 모두 해당되지만 반드시 해당될 필요는 없습니다.C 컴파일러는 모든 변수를 해시테이블에 넣고 런타임(또는 그와 비슷한 것)에 검색할 수 있습니다.실제로 초기 JavaScript 인터프리터는 바로 그렇게 했습니다(현재는 Just-In-TIME 컴파일러는 훨씬 더 원시적인 결과를 낳습니다).

특히 VC++, GCC, LLVM과 같은 일반적인 컴파일러의 경우: 컴파일러는 일반적으로 메모리 내의 위치에 변수를 할당합니다.글로벌 또는 스태틱스코프의 변수는 프로그램 실행 중에 변경되지 않는 고정 주소를 얻는 반면 함수 내의 변수는 스택주소, 즉 함수가 호출될 때마다 변경되는 현재 스택포인터에 상대적인 주소를 가져옵니다.(이는 지나치게 단순합니다.)스택 주소는 함수가 반환되는 즉시 비활성화되지만 실질적으로 사용할 오버헤드가 0이라는 이점이 있습니다.

변수에 주소가 할당되면 변수 이름은 더 이상 필요하지 않으므로 폐기됩니다.이름의 종류에 따라 이름은 전처리 시(매크로 이름의 경우), 컴파일 시(스태틱 및 로컬 변수/함수의 경우) 및 링크 시간(글로벌 변수/함수의 경우)에 폐기될 수 있습니다.기호를 내보내는 경우(다른 프로그램이 액세스할 수 있도록 표시됨), 보통 이름은 메모리와 디스크 공간을 차지하는 "심볼 테이블" 어딘가에 남아 있습니다.

컴파일러가 variable_name을 볼 때마다 0xaaaaaaaaaaaaaaaaaaaaaaaaaa

네.

그렇다면 메모리를 사용해서 대체해야 하지 않을까요?

네, 하지만 컴파일러가 코드를 컴파일한 후에 왜 메모리에 신경을 쓰죠?

언급URL : https://stackoverflow.com/questions/14612314/how-are-variable-names-stored-in-memory-in-c

반응형