473,232 Members | 1,568 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,232 software developers and data experts.

Static initialization dependency -- Think in C++ 2nd

I will present very long code, hope someone will read it all, and teach me
something like tom_usenet.

This question comes to me when i read <<Think in C++>> 2nd, chapter 10 ,
name control, section "Static initialization dependency". There is a
example to show how to solve the prolem involved with a technique first
poineered by Jerry Schwarz while creating the iostream library (because the
definitions for cin, cout, and cerr are static and live in a separate file).

The idea is to use a additional class responsible for the dynamic
initialization of your library¡¯s static objects.

Here in the code following, the static objects is std::ofstream out,
intended to be used as a log file maybe, and the addition class is
Initializer. In class Initializer's constructor, out initialize the log
file... but code stop there with a access voilation exception.......

I'm eager to know why....

----------------------------------------------------------------------------
----
//: C10:Initializer.h
// Static initialization technique
#ifndef INITIALIZER_H
#define INITIALIZER_H
#include <iostream>
#include <fstream>
extern std::ofstream out;

class Initializer {
static int initCount;
public:
Initializer();
~Initializer();
};
// The following creates one object in each
// file where Initializer.h is included, but that
// object is only visible within that file:
static Initializer init;
#endif // INITIALIZER_H ///:~
-----------------------------------------------------------------------

//Initializer.cpp
#include "Initializer.h"
#include <fstream>
#include <iostream>
Initializer::Initializer(){
// Initialize first time only
if(initCount++ == 0) {
std::cout << out.is_open() << std::endl; //return 0
// to test if out is good to work with
///////////////////////////////////////////////////////////////////
out.open("hello.txt"); // program stuck here......
///////////////////////////////////////////////////////////////////
// debug give infomation like this :
//First-chance exception in test.exe: 0xC0000005: Access Violation.
// i use VC++ 6.0.
}
}
Initializer::~Initializer()
{
std::cout << "~Initializer()" << std::endl;
// Clean up last time only
if(--initCount == 0) {
out.close();
// Any necessary cleanup here
}
}
------------------------------------------------------------------------
//: C10:InitializerDefs.cpp {O}
// Definitions for Initializer.h
#include "Initializer.h"
#include <fstream>
// Static initialization will force
// all these values to zero:
std::ofstream out;
int Initializer::initCount;
///:~
------------------------------------------------------------------------
// test file......
//: C10:Initializer2.cpp
//{L} InitializerDefs Initializer
// Static initialization
#include "Initializer.h"
using namespace std;

int main() {
out << "hello" << endl;
return 0;
} ///:~
------------------------------------------------------------------------
Jul 22 '05 #1
1 4596
Tom
"Qin Chen" <wi*******@etang.com> wrote in message news:<c1*************@ID-226321.news.uni-berlin.de>...
I will present very long code, hope someone will read it all, and teach me
something like tom_usenet.

This question comes to me when i read <<Think in C++>> 2nd, chapter 10 ,
name control, section "Static initialization dependency". There is a
example to show how to solve the prolem involved with a technique first
poineered by Jerry Schwarz while creating the iostream library (because the
definitions for cin, cout, and cerr are static and live in a separate file).
I just downloaded the book and had a look, and unfortunately the
solution he proposes only works for POD objects. For non-PODs, the
details are somewhat different, and worse, there is no completely
portable way to do it.

The idea is to use a additional class responsible for the dynamic
initialization of your library¡¯s static objects.
Right, however, you need to use some platform specific trickery to
initialize the ostream. Read on...

Here in the code following, the static objects is std::ofstream out,
intended to be used as a log file maybe, and the addition class is
Initializer. In class Initializer's constructor, out initialize the log
file... but code stop there with a access voilation exception.......

I'm eager to know why....
It's because "out" hasn't been constructed by the time your
Initializer object attempts to access it (calling "open"). The order
that global objects from different translation units are initialized
in is not well defined - this is the infamous "static initialization
dependency fiasco". There are a number of ways of solving it, all of
which depend on some level of platform specific behaviour or compiler
extensions. I'll present a mostly portable version.

Incidently, one non-portable solution, for MSVC, is:
Add the following to InitializerDefs.cpp, just before the "out"
definition:
#pragma init_seg(compiler)

That forces the compiler to initialize objects declared in that
segment before initializing normal globals. Read on for a more
portable solution.

----------------------------------------------------------------------------
----
//: C10:Initializer.h
// Static initialization technique
#ifndef INITIALIZER_H
#define INITIALIZER_H
#include <iostream>
#include <fstream>
For my "portable" solution you need
extern std::ofstream* const out_pointer;
static std::ofstream& out = *out_pointer; //dynamic initialization

class Initializer {
static int initCount;
public:
Initializer();
~Initializer();
};
// The following creates one object in each
// file where Initializer.h is included, but that
// object is only visible within that file:
static Initializer init;
#endif // INITIALIZER_H ///:~
-----------------------------------------------------------------------

//Initializer.cpp
#include "Initializer.h"
#include <fstream>
#include <iostream>
Initializer::Initializer(){
// Initialize first time only
if(initCount++ == 0) {
std::cout << out.is_open() << std::endl; //return 0
// to test if out is good to work with
///////////////////////////////////////////////////////////////////
Here you should construct the stream in the storage that the reference
points to:
new (out_pointer) std::ofstream("hello.txt");
out.open("hello.txt"); // program stuck here......
Now you don't need that.
///////////////////////////////////////////////////////////////////
// debug give infomation like this :
//First-chance exception in test.exe: 0xC0000005: Access Violation.
// i use VC++ 6.0.
}
}
Initializer::~Initializer()
{
std::cout << "~Initializer()" << std::endl;
// Clean up last time only
if(--initCount == 0) {
out.close();
Here you need to destroy the stream:
typedef std::ofstream ofs;
out_pointer->~ofs();
// Any necessary cleanup here
}
}
------------------------------------------------------------------------
//: C10:InitializerDefs.cpp {O}
// Definitions for Initializer.h
#include "Initializer.h"
#include <fstream>
// Static initialization will force
// all these values to zero:
std::ofstream out;
Here's where you do the "portable" hack:

#include <cstddef>

namespace
{

union aligner
{
long double v1;
double v2;
long v3;
void (*v4)();
class dummy;
void (dummy::*v5);
void (dummy::*v6)();
void* v7;
};

std::size_t const temp_aligner_count = sizeof(std::ofstream) /
sizeof(aligner);
std::size_t const aligner_count = sizeof(std::ofstream) %
sizeof(aligner) ?
temp_aligner_count + 1 : temp_aligner_count;

//this is enough storage to fit the stream in:
aligner out_storage[aligner_count]; //hope this is properly aligned!

} //close anon namespace

//here's more "trickery". This is static initialization, hence carried
out
//before program start (and before init's etc. get initialized.
std::ofstream* const out_pointer =
reinterpret_cast<std::ofstream*>(out_storage);

int Initializer::initCount;
///:~
------------------------------------------------------------------------
// test file......
//: C10:Initializer2.cpp
//{L} InitializerDefs Initializer
// Static initialization
#include "Initializer.h"
using namespace std;

int main() {
out << "hello" << endl;
return 0;
} ///:~


With those changes, the above should work fine.

Tom
Jul 22 '05 #2

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

49
by: bearophileHUGS | last post by:
Adding Optional Static Typing to Python looks like a quite complex thing, but useful too: http://www.artima.com/weblogs/viewpost.jsp?thread=85551 I have just a couple of notes: Boo...
3
by: DanielBradley | last post by:
Hello all, I have recently been porting code from Linux to cygwin and came across a problem with static const class members (discussed below). I am seeking to determine whether I am programming...
12
by: chandu | last post by:
hello, i want to know usage of static methods in a class. is it advantageous or disadvantage to use more static methods in a class. thank u
5
by: Jesper Schmidt | last post by:
When does CLR performs initialization of static variables in a class library? (1) when the class library is loaded (2) when a static variable is first referenced (3) when... It seems that...
14
by: Jeroen | last post by:
Hi all, I've got a question about writing a library. Let me characterize that library by the following: * there is a class A which is available to the user * there is a class B that is used...
10
by: n.torrey.pines | last post by:
Are global variables (and const's) guaranteed to be initialized before static class members (and methods) ? const int x = 19907; int get_x() { return x; } // another compilation unit: ...
3
by: Steve Folly | last post by:
Hi, I had a problem in my code recently which turned out to be the 'the "static initialization order fiasco"' problem (<http://www.parashift.com/c++-faq-lite/ctors.html#faq-10.12>) The FAQ...
20
by: JohnQ | last post by:
The way I understand the startup of a C++ program is: A.) The stuff that happens before the entry point. B.) The stuff that happens between the entry point and the calling of main(). C.)...
6
by: gs | last post by:
Hi, I want to know that when memory get allocated to static data member of a class. class A { static int i; }
3
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 3 Jan 2024 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM). For other local times, please check World Time Buddy In...
0
by: jianzs | last post by:
Introduction Cloud-native applications are conventionally identified as those designed and nurtured on cloud infrastructure. Such applications, rooted in cloud technologies, skillfully benefit from...
2
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 7 Feb 2024 starting at 18:00 UK time (6PM UTC) and finishing at about 19:30 (7.30PM). In this month's session, the creator of the excellent VBE...
0
by: fareedcanada | last post by:
Hello I am trying to split number on their count. suppose i have 121314151617 (12cnt) then number should be split like 12,13,14,15,16,17 and if 11314151617 (11cnt) then should be split like...
0
Git
by: egorbl4 | last post by:
Скачал я git, хотел начать настройку, а там вылезло вот это Что это? Что мне с этим делать? ...
0
by: MeoLessi9 | last post by:
I have VirtualBox installed on Windows 11 and now I would like to install Kali on a virtual machine. However, on the official website, I see two options: "Installer images" and "Virtual machines"....
0
by: DolphinDB | last post by:
Tired of spending countless mintues downsampling your data? Look no further! In this article, you’ll learn how to efficiently downsample 6.48 billion high-frequency records to 61 million...
0
by: Aftab Ahmad | last post by:
Hello Experts! I have written a code in MS Access for a cmd called "WhatsApp Message" to open WhatsApp using that very code but the problem is that it gives a popup message everytime I clicked on...
0
by: Aftab Ahmad | last post by:
So, I have written a code for a cmd called "Send WhatsApp Message" to open and send WhatsApp messaage. The code is given below. Dim IE As Object Set IE =...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.