HOW TO: Use #pragma init_seg to Control Static Construction

This article was previously published under Q104248
This article has been archived. It is offered "as is" and will no longer be updated.
In the Microsoft C++ Compiler, it is possible to control when your staticobjects, declared at file scope, are constructed and destructed by usingthe #pragama init_seg preprocessor directive.


There are four options for the init_seg preprocessor directive: compiler,lib, user, and "user_defined_segment_name." In source code, this directivewould have the form:
   #pragma init_seg(compiler)   #pragma init_seg(lib)   #pragma init_seg(user)   #pragma init_seg("user_defined_segment_name")				
NOTE: Only one init_seg directive can appear in a single source file.Otherwise, the compiler generates "error C2356: initialization segment mustnot change during translation unit."

The purpose of this directive is to give the developer the ability to groupthe constructors in an application. This would be useful if some objectsrelied upon the existence of other objects to function correctly. Objectsthat are grouped together using #pragma init_seg(compiler) are constructedbefore all other objects and destroyed after all other objects in theapplication. This is used for objects in the run-time libraries. Forexample, because cin and cout may or may not be constructed yet, usingthese objects in your constructor or destructor that uses theinit_seg(compiler) #pragma would be unwise.

Objects that are grouped together using #pragma init_seg(lib) areconstructed after and destructed before objects that are in modulescompiled with #pragma init_seg(compiler), but before all other objects inthe application. Objects that are grouped together using #pragmainit_seg(user) are constructed after and destructed before objects that arein modules compiled with #pragma init_seg(compiler) and #pragmainit_seg(lib). In other words, objects that are grouped together using#pragma init_seg(user) are constructed and destructed at the same time asall other static objects that were not grouped using #pragma init_seg.

The documentation isn't totally clear on this point. It states that objectsin the user group are constructed last. This means that these objects areconstructed after and destructed before the compiler and lib groups. Oneway that you can control the order of construction and destruction withineach group is to change the order of linking. Modules that appear earlierin the link line will be constructed after and destructed before modulesthat appear later in the link line that are in the same init_seg group.Constructors are called in reverse order of their appearance in thesegments.

It is important to note that the C++ language does not guarantee any orderof construction for nonderived objects; the C++ language guarantees thatthose objects will be constructed, and that base classes will beconstructed before classes that derive from them.

The #pragma init_seg("user_defined_segment_name") preprocessor directiveputs the addresses of the constructors into the logical segment"user_defined_segment_name". This option is useful only if you modify thestartup code to call these constructors.

The following code sample (four source files) demonstrates the above ideas.After compiling all source files, link them in the two ways shown below andrun the resultant executables. The output from each will show whichinit_seg options are dependent on link order and which are not.

With Visual C++ 32-bit Edition versions, use:
   link file1 file2 file3 file4 /out:demo1.exe   link file4 file3 file2 file1 /out:demo2.exe				
With Visual C++ 16-bit versions, use:
   link file1 file2 file3 file4, demo1;   link file4 file3 file2 file1, demo2;				

Sample Code

// file1.cpp// command line: cl /c file1.cpp#pragma init_seg(compiler)#include<stdio.h>class MyCompClass{public:      MyCompClass(){ printf("In the ctor of MyCompClass\n");}      ~MyCompClass(){ printf("In the dtor of MyCompClass\n");}} MyComp;// file2.cpp// command line: cl /c file2.cpp#pragma init_seg(lib)#include<iostream.h>class MyLibClass{public:      MyLibClass(){cout<<"In the ctor of MyLibClass"<<endl;}      ~MyLibClass(){cout<<"In the dtor of MyLibClass"<<endl;}} MyLib;// file3.cpp// command line: cl /c file3.cpp#pragma init_seg(user)#include<iostream.h>class MyUserClass{public:      MyUserClass(){cout<<"In the ctor of MyUserClass"<<endl;}      ~MyUserClass(){cout<<"In the dtor of MyUserClass"<<endl;}} MyUser;// file4.cpp// command line: cl /c file4.cpp#include<iostream.h>class MyRegularClass{public:      MyRegularClass(){cout<<"In the ctor of MyRegularClass"<<endl;}      ~MyRegularClass(){cout<<"In the dtor of MyRegularClass"<<endl;}} MyRegular;void main(){}				
7.00 7.00a 8.00

Article ID: 104248 - Last Review: 12/04/2015 09:43:38 - Revision: 3.1

Microsoft Visual C++ 1.0 Professional Edition, Microsoft Visual C++ 1.5 Professional Edition, Microsoft Visual C++ 1.0 Professional Edition, Microsoft Visual C++ 2.0 Professional Edition, Microsoft Visual C++ 2.1, Microsoft Visual C++ 4.0 Standard Edition, Microsoft Visual C++ 5.0 Standard Edition, Microsoft Visual C++ 6.0 Service Pack 5

  • kbnosurvey kbarchive kbcode kbhowto kbhowtomaster kblangcpp KB104248