신입 게임 개발자의 프로그래밍 일기

[C++ 입문자에서 벗어나기]Chapter_2: 선언과 정의#2 본문

Language/C++

[C++ 입문자에서 벗어나기]Chapter_2: 선언과 정의#2

KFGD 2017. 11. 8. 14:22

[C++ 입문자에서 벗어나기]Chapter_2: 선언과 정의#2


이번 포스팅에서는 "초기화된 전역 변수와 초기화되지 않은 전역 변수"에 대해서 다뤄볼 생각입니다.


[초기화된 전역 변수와 초기화되지 않은 전역 변수]


아래의 코드를 봐주시길 바랍니다.


  


전역 변수 형태로 총 4개의 변수들이 정의되어 있습니다.

우리는 이미 이전 포스팅에서 전역 변수가 자동 초기화가됨을 알고 있습니다.

위 코드를 실행 시키면 0057이라는 출력값이 나오게 된다는 것은 쉽게 알 수 있겠죠.


그런데 위 전역 변수들은 C++의 어느 가상 메모리 영역에 위치하게 될까요?


g_C는 확실하게 Data영역에 위치할 것 같습니다.

5라는 상수로 변수를 초기화하는 정의문을 가지고 있으니까요


그렇다면 나머지 3개는 어떨까요?

먼저, g_A에 대해 이야기해봅시다.

g_A는 어느 값으로도 초기화되지 않으니까 BSS영역일 거 같네요.


그러면 g_B는 어떨까요?

g_B는 0으로 초기화했으니까 Data영역일 거 같습니다.

그런데 BSS영역은 초기화되지 않은 값들을 넣어놓고 다 0으로 설정해놓는 것인데....

0으로 초기화하면 정말 Data영역으로 가는건지가 약간 의문스러워서 StackOverflow에 물어봤습니다.


https://stackoverflow.com/questions/8721475/if-a-global-variable-is-initialized-to-0-will-it-go-to-bss

위 게시글의 답변을 요약하면 이렇습니다.

-GCC는 기본적으로는 0으로 초기화된 변수들에 대해서 BSS영역에 저장시킵니다. 

 이렇게함으로써 실행 바이너리의 크기를 절약할 수 있습니다.

-GCC 옵션은 기본적으로는 -fzero-initialized-in-bss로 설정되어 있지만 -fno-zero-initialized-in-bss 옵션을 줄 시에는 0으로 초기화된 변수들을 BSS영역이 아닌 Data영역에 저장시킬 수 있습니다.


그러면 마지막으로 g_D에 대해 이야기해봅시다.

g_D는 함수로 값을 초기화하는데 결론부터 이야기드리자면 g_D는 BSS영역에 저장됩니다.

상수로 초기화되는 전역 변수들만이 Data영역에 저장되고 함수(생성자 포함)로 초기화를 진행하는 전역변수들의 경우 BSS영역에 저장되고 프로세스 실행 후에야 함수의 반환값으로 값이 설정됩니다.


위 코드가 실행될 시에 전역 변수들의 값들이 어떻게 변동되는 지를 순차적으로 간단히 살펴보겠습니다.

먼저 프로그램을 동작시키면 프로세스가 생성되고 스레드가 생성되며 스레드에서 main함수를 호출하기 이전에 먼저 CRT_Startup 함수를 호출합니다.

이 때, CRT_Startup함수가 호출되기 이전에 g_A, g_B, g_D는 0으로 g_C는 5로 값이 설정된 상태입니다.

CRT_Startup이 여러 함수를 호출하다가 초기화 처리 함수를 호출 할 때, g_D는 7이라는 값을 할당받게 됩니다.

이후에 CRT_Startup이 필요한 모든 함수들이 호출된 다음에서야 main함수가 호출되고 cout함수를 통해 출력문들이 출력되게 됩니다.


이제 글로써만 말한 전역 변수의 저장 공간을 objdump를 활용하여 직접 확인해봅시다.

우선 gcc로 default로 컴파일한 out파일을 조사한 결과입니다.




상수 5로 초기화 g_C를 제외한 모두가 BSS 영역에 위치함을 확인할 수 있습니다.

이번엔 -fno-zero-initialized-in-bss 옵션을 주고나서 컴파일한 out파일을 조사해봤습니다.




g_B의 위치가 data 섹션으로 바뀌었음을 알 수 있습니다.


추가적으로 간단히 정적 지역 변수에 대해서 언급만 해보겠습니다.

정적 지역 변수는 정의된 함수 내에서만 접근이 가능한 정적 변수로 초기화가 프로세스 시작시 초기화가 되지 않고

해당 변수가 정의된 함수가 최초 호출 시에 초기화가 진행됩니다.

함수 호출 처음에만 초기화가 되며 그 이후에는 초기화가 진행되지 않습니다.


Comments