init_seg

Specifies a keyword or code section that affects the order in which startup code is executed. Because initialization of global static objects can involve executing code, you must specify a keyword that defines when the objects are to be constructed. It is particularly important to use the init_seg pragma in dynamic-link libraries (DLLs) or libraries requiring initialization.

The options to the init_seg pragma are:

compiler

Reserved for Microsoft C run-time library initialization. Objects in this group are constructed first.

lib

Available for third-party class-library vendors' initializations. Objects in this group are constructed after those marked as compiler but before any others.

user

Available to any user. Objects in this group are constructed last.

section-name

Allows explicit specification of the initialization section. Objects in a user-specified section-name are not implicitly constructed; however, their addresses are placed in the section named by section-name.

The section name you give will contain pointers to helper functions that will construct the global objects declared in that module after the pragma.

For a list of names you should not use when creating a section, see /SECTION.

func-name

Specifies a function to be called in place of atexit when the program exits. This helper function also calls atexit with a pointer to the destructor for the global object. If you specify a function identifier in the pragma of the form,

Example

// 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]; //ptrs to those dtors. Watch out for overflow!
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 data_seg(".mine$a")
PF InitSegStart = (PF)1;
#pragma data_seg(".mine$z")
PF InitSegEnd = (PF)1;
#pragma data_seg()
// 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 () {
PF *x = &InitSegStart;
for (++x; x<&InitSegEnd; ++x) {
if (*x) (*x)();
}
}
void DestroyObjects () {
while (cxpf>0) {
--cxpf;
(pfx[cxpf])();
}
}
#pragma init_seg(".mine$m",myexit)
// I get to call the ctor & dtor from now on.
A bbbb;
A cccc;
int main () {
InitializeObjects();
// do some stuff here
DestroyObjects();
return 0;
}