init_seg
pragma
C++ 특정
시작 코드가 실행되는 순서에 영향을 주는 키워드 또는 코드 섹션을 지정합니다.
구문
#pragma init_seg(
{compiler
| |lib
user
| "section-name" [,
func-name ] })
설명
용어 세그먼트 와 섹션 은 이 문서에서 동일한 의미를 갖습니다.
전역 정적 개체를 초기화하는 데 코드가 필요한 경우가 있기 때문에 개체를 생성할 시기를 지정해야 합니다. 특히 DLL(동적 연결 라이브러리) 또는 초기화가 필요한 라이브러리에서 사용하는 init_seg
pragma 것이 중요합니다.
옵션은 init_seg
pragma 다음과 같습니다.
compiler
Microsoft C 런타임 라이브러리 초기화용으로 예약되어 있습니다. 이 그룹의 개체는 처음 생성됩니다.
lib
타사 클래스 라이브러리 공급업체의 초기화에 사용할 수 있습니다. 이 그룹의 개체는 표시된 compiler
개체 뒤와 다른 개체 앞에 생성됩니다.
user
모든 사용자가 사용할 수 있습니다. 이 그룹의 개체는 마지막에 생성됩니다.
section-name
초기화 섹션의 명시적 지정을 허용합니다. 사용자가 지정한 섹션 이름의 개체는 암시적으로 생성되지 않습니다. 그러나 해당 주소는 섹션 이름으로 명명된 섹션에 배치됩니다.
지정한 섹션 이름에는 해당 모듈에서 선언된 전역 개체를 생성하는 도우미 함수에 대한 포인터가 pragma 포함됩니다.
섹션을 만들 때 사용하지 않아야 하는 이름 목록은 다음을 참조하세요 /SECTION
.
func-name
프로그램이 종료되면 atexit
대신 호출될 함수를 지정합니다. 또한 이 도우미 함수는 전역 개체의 소멸자에 대한 포인터를 사용하여 호출 atexit
합니다. 폼에서 함수 식별자를 pragma 지정하는 경우
int __cdecl myexit (void (__cdecl *pf)(void))
C 런타임 라이브러리의 atexit
대신 해당 함수가 호출됩니다. 개체를 삭제할 준비가 되면 호출할 소멸자 목록을 작성할 수 있습니다.
초기화를 지연해야 하는 경우(예: DLL에서) 섹션 이름을 명시적으로 지정할 수 있습니다. 그러면 코드에서 각 정적 개체에 대한 생성자를 호출해야 합니다.
atexit
대체 식별자에는 따옴표가 없습니다.
개체는 다른 XXX_seg
pragma 지시문에 정의된 섹션에 계속 배치됩니다.
모듈에서 선언된 개체는 C 런타임에 의해 자동으로 초기화되지 않습니다. 코드는 초기화를 수행해야 합니다.
기본적으로 init_seg
섹션은 읽기 전용입니다. 섹션 이름이면 .CRT
컴파일러는 읽기, 쓰기로 표시된 경우에도 자동으로 특성을 읽기 전용으로 변경합니다.
번역 단원에서는 두 번 이상 지정할 init_seg
수 없습니다.
개체에 코드에 명시적으로 정의된 사용자 정의 생성자가 없더라도 컴파일러에서 생성할 수 있습니다. 예를 들어 v 테이블 포인터를 바인딩하는 포인터를 만들 수 있습니다. 필요한 경우 코드는 컴파일러에서 생성된 생성자를 호출합니다.
예시
// pragma_directive_init_seg.cpp
#include <stdio.h>
#pragma warning(disable : 4075)
typedef void (__cdecl *PF)(void);
int cxpf = 0; // number of destructors we need to call
PF pfx[200]; // pointers to destructors.
int myexit (PF pf) {
pfx[cxpf++] = pf;
return 0;
}
struct A {
A() { puts("A()"); }
~A() { puts("~A()"); }
};
// ctor & dtor called by CRT startup code
// because this is before the pragma init_seg
A aaaa;
// The order here is important.
// Section names must be 8 characters or less.
// The sections with the same name before the $
// are merged into one section. The order that
// they are merged is determined by sorting
// the characters after the $.
// InitSegStart and InitSegEnd are used to set
// boundaries so we can find the real functions
// that we need to call for initialization.
#pragma section(".mine$a", read)
__declspec(allocate(".mine$a")) const PF InitSegStart = (PF)1;
#pragma section(".mine$z",read)
__declspec(allocate(".mine$z")) const PF InitSegEnd = (PF)1;
// The comparison for 0 is important.
// For now, each section is 256 bytes. When they
// are merged, they are padded with zeros. You
// can't depend on the section being 256 bytes, but
// you can depend on it being padded with zeros.
void InitializeObjects () {
const PF *x = &InitSegStart;
for (++x ; x < &InitSegEnd ; ++x)
if (*x) (*x)();
}
void DestroyObjects () {
while (cxpf>0) {
--cxpf;
(pfx[cxpf])();
}
}
// by default, goes into a read only section
#pragma init_seg(".mine$m", myexit)
A bbbb;
A cccc;
int main () {
InitializeObjects();
DestroyObjects();
}
A()
A()
A()
~A()
~A()
~A()