0

How can a global variable in a shared library unset itself? I was experimenting with a very simple library where I noticed that a global std::string does not hold its value. Here's the full code I have:

in libfoo.cxx:

#include <string>
#include <iostream>

using namespace std;

static string name;

__attribute__((constructor))
static void init() {
  ios_base::Init init_ios;

  name = "LIBFOO";
  cout << "init name: " << name << endl;
}

extern "C" const char *get_name() {
  return name.c_str();
}

in libfoo.h:

#ifndef LIBFOO_H
#define LIBFOO_H

extern "C" const char *get_name();

#endif

In test.cxx:

#include <iostream>
#include "libfoo.h"

int main() {
  std::cout << "main name: " << get_name() << std::endl;
}

Build:

g++ -o libfoo.so -shared -fPIC libfoo.cxx
g++ -o test test.c -L. -lfoo

Run:

LD_LIBRARY_PATH=$PWD ./test

Output:

init name: LIBFOO
main name: 

Where did the value of name go? How could the variable unset itself?

MEE
  • 2,114
  • 17
  • 21
  • Try printing the *pointer* in both the library and the `main` function. Not only in the libraries `init` function but in the `get_name` function too. – Some programmer dude Nov 24 '16 at 14:48
  • `(void *) name.c_str()` in `init()` is different from that in `get_name()`. How could that happen? – MEE Nov 24 '16 at 14:55

1 Answers1

0

You are stepping on muddy ground here as order of constructors of different types (C++ ctors vs. attribute ctors) isn't well defined and may very across compilers (see e.g. c-static-initialization-vs-attribute-constructor ). So my guess is that firstly you assign to name and then the default constructor runs, resetting it to empty string. You can verify this by stepping through init code under gdb.

Community
  • 1
  • 1
yugr
  • 19,769
  • 3
  • 51
  • 96
  • I am using GCC. According to the link you posted, objects are initialized in the declaration order. So "name" in the global scope is initialized before init() is called. – MEE Nov 24 '16 at 15:38
  • Right, I gave it as illustration of potential problems. That's why I suggested to step through initializers in gdb to verify if that's causing your issues. – yugr Nov 24 '16 at 15:47
  • I just did and you're absolutely right! `name` in the global scope is re-initialized (default constructor) _after_ `init()` returns. Changing the init priorities fixed it. Is that a bug in GCC? Or are the docs outdated? I am using GCC 5.4.0. – MEE Nov 24 '16 at 15:51
  • 1
    I think folks in other question might have got the wording wrong - it only says that rules for specifying priorities for attribute ctors and C++ ctors are the same (i.e. 101 to 65535), not that GCC will treat both types of ctors equally. You can try reporting to GCC BZ but I'm sceptical... – yugr Nov 24 '16 at 16:12