Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Global vector emptying itself between calls?

Tags:

c++

I have a vector in a header, like so:

extern std::vector<Foo> g_vector;

In the associated cpp file I have this:

std::vector<Foo> g_vector;

I also have a class Bar, and in it's constructor it will add some stuff to g_vector, like so:

Bar::Bar(/* stuff */)
{
    // do things
    std::cout << g_vector.size() << std::endl;
    g_vector.push_back(somefoo);
    std::cout << g_vector.size() << std::endl;
}

If I declare a Bar inside a function, like a sane person, it appears to work fine. However, if I want to declare a Bar outside of a function, weird things happen. For example, I have a Bar declared in MyFile1.cpp and in MyFile2.cpp, and because of my cout statements in Bar I can see the Foo get pushed into the vector, but when the next Bar runs its constructor the vector's size is 0 again. In other words, my output is

0
1
0
1

What gives? Just to be extra double sure, I also tried printing out &g_vector to make sure it was actually push_backing into the right vector, and the addresses all match. For what it's worth, it doesn't matter what order these things go in to the vector. I'm not concerned with the initialization order or anything.

like image 552
Alex Avatar asked Sep 24 '11 21:09

Alex


2 Answers

Not sure what the issue really is, but I guess the following pattern will help solve it: define an accessor to the global variable and allocate it as a static function variable as shown below.

In the header file:

std::vector<Foo> &getGlobalVector();

In the cpp file:

std::vector<Foo> &getGlobalVector()
{
  static std::vector<Foo> s_vector;
  return s_vector;
}

This pattern is inspired from Andrei Alexandrescu's "generic singleton" implementation in Modern C++ design.

I've taken the habit of systematically using this pattern whenever I fell upon an existing global variable while maintaining existing applications (or in the rare occasions I actually chose to use one myself), and it may have helped in eliminating a couple of hard-to-reproduce bugs in said applications.

At any rate, this should really help avoiding any multiple-initialization or order-of-initialization related issue.

like image 132
ZeRemz Avatar answered Oct 20 '22 16:10

ZeRemz


Order of initialization of global values is not defined.

Read here about the static initialization fiasco.

When you declare Bar in a function - the g_vector will be initialized before, because its promised to be initialized before the program runs. If Bar is a global variable - then you have a problem.

like image 6
littleadv Avatar answered Oct 20 '22 18:10

littleadv