John John - 9 days ago 6
C++ Question

Global string unsets itself in shared library

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?

Answer

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.

Comments