CRT 초기화CRT Initialization

이 항목에서는 CRT가 네이티브 코드에서 전역 상태를 초기화하는 방법에 대해 설명합니다.This topic describes how the CRT initializes global states in native code.

기본적으로 링커는 자체 시작 코드를 제공하는 CRT 라이브러리를 포함합니다.By default, the linker includes the CRT library, which provides its own startup code. 이 시작 코드는 CRT 라이브러리를 초기화하고 전역 이니셜라이저를 호출한 다음 콘솔 응용 프로그램에 대해 사용자 제공 main 함수를 호출합니다.This startup code initializes the CRT library, calls global initializers, and then calls the user-provided main function for console applications.

전역 개체 초기화Initializing a Global Object

다음 코드를 살펴보세요.Consider the following code:

int func(void)  
{  
    return 3;  
}  

int gi = func();  

int main()  
{  
    return gi;  
}  

C/C++ 표준에 따라 func()을 실행하기 전에 main()를 호출해야 합니다.According to the C/C++ standard, func() must be called before main() is executed. 하지만 누가 호출할까요?But who calls it?

이를 결정하는 한 방법은 func()에서 중단점을 설정하고, 응용 프로그램을 디버깅하고, 스택을 검토하는 것입니다.One way to determine this is to set a breakpoint in func(), debug the application, and examine the stack. 이는 CRT 소스 코드가 Visual Studio에 포함되어 있기 때문에 가능합니다.This is possible because the CRT source code is included with Visual Studio.

스택에서 함수를 찾을 때는 CRT가 함수 포인터 목록을 반복하며 함수 포인터를 발견하면서 각 포인터를 호출하는 것을 확인할 수 있습니다.When you browse the functions on the stack, you will find that the CRT is looping through a list of function pointers and calling each one as it encounters them. 이러한 함수는 func() 또는 클래스 인스턴스에 대한 생성자와 유사합니다.These functions are either similar to func() or constructors for class instances.

CRT는 Visual C++ 컴파일러에서 함수 포인터 목록을 가져옵니다.The CRT obtains the list of function pointers from the Visual C++ compiler. 컴파일러는 전역 이니셜라이저를 발견하면 .CRT$XCU 섹션에 동적 이니셜라이저를 생성합니다. 여기서 CRT는 섹션 이름이고 XCU는 그룹 이름입니다.When the compiler sees a global initializer, it generates a dynamic initializer in the .CRT$XCU section (where CRT is the section name and XCU is the group name). 이러한 동적 이니셜라이저 목록을 가져오려면 dumpbin /all main.obj 명령을 실행한 다음 .CRT$XCU 섹션을 검색합니다(main.cpp가 C 파일이 아니라 C++ 파일로 컴파일된 경우).To obtain a list of those dynamic initializers run the command dumpbin /all main.obj, and then search the .CRT$XCU section (when main.cpp is compiled as a C++ file, not a C file). 이는 다음과 유사합니다.It will be similar to the following:

SECTION HEADER #6  
.CRT$XCU name  
       0 physical address  
       0 virtual address  
       4 size of raw data  
     1F2 file pointer to raw data (000001F2 to 000001F5)  
     1F6 file pointer to relocation table  
       0 file pointer to line numbers  
       1 number of relocations  
       0 number of line numbers  
40300040 flags  
         Initialized Data  
         4 byte align  
         Read Only  

RAW DATA #6  
  00000000: 00 00 00 00                                      ....  

RELOCATIONS #6  
                                                Symbol    Symbol  
 Offset    Type              Applied To         Index     Name  
 --------  ----------------  -----------------  --------  ------  
 00000000  DIR32                      00000000         C  ??__Egi@@YAXXZ (void __cdecl `dynamic initializer for 'gi''(void))  

CRT는 두 포인터를 정의합니다.The CRT defines two pointers:

  • __xc_a.CRT$XCA__xc_a in .CRT$XCA

  • __xc_z.CRT$XCZ__xc_z in .CRT$XCZ

    두 그룹 모두에 __xc_a__xc_z를 제외하고 정의된 다른 기호가 없습니다.Both groups do not have any other symbols defined except __xc_a and __xc_z.

    링커는 다양한 .CRT 그룹을 읽을 때 해당 그룹을 한 섹션에서 결합하고 사전순으로 정렬합니다.Now, when the linker reads various .CRT groups, it combines them in one section and orders them alphabetically. 즉, Visual C++ 컴파일러가 .CRT$XCU에 넣는 사용자 정의 전역 이니셜라이저가 항상 .CRT$XCA 뒤와 .CRT$XCZ 앞에 옵니다.This means that the user-defined global initializers (which the Visual C++ compiler puts in .CRT$XCU) will always come after .CRT$XCA and before .CRT$XCZ.

    이 섹션은 다음과 유사합니다.The section will resemble the following:

.CRT$XCA  
            __xc_a  
.CRT$XCU  
            Pointer to Global Initializer 1  
            Pointer to Global Initializer 2  
.CRT$XCZ  
            __xc_z  

따라서 CRT 라이브러리는 __xc_a__xc_z를 모두 사용하여 전역 이니셜라이저 목록의 시작과 끝을 결정합니다. 이는 이미지가 로드된 후 메모리에서 전역 이니셜라이저가 배치되는 방식 때문입니다.So, the CRT library uses both __xc_a and __xc_z to determine the start and end of the global initializers list because of the way in which they are laid out in memory after the image is loaded.

참고 항목See Also

CRT 라이브러리 기능CRT Library Features