Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Mystic segfault when using dlopen with static function with static variables inside it.

190 views
Skip to first unread message

Markku Linnoskivi

unread,
Jan 16, 2012, 3:22:39 AM1/16/12
to
Environment: Linux + g++ (4.3.X)
Let there be the following classes:
//libfoo <<<
struct Bar
{
Bar()
: s()
{}
Bar(const std::string& s_)
: s(s_)
{}
std::string s;
};

struct Foo
{
static Bar getBar()
{
static Bar b;
static done = false;
if (done)
{
return b;
}
done = true;
std::stringstream s;
s << __FILE__ ;
b = Bar(s.str());
return b;
}
};

//libfoo >>>>
//libX <<<
struct FooObj
{
//has instance of Foo and calls Foo:getBar()
};

extern "C"
{
FooObj* create()
{
return new FooObj;
}
}

//libX >>>

The context is a plugin system where the plugins use a common library
(libfoo) and appfoo is the host for the plugins.
There is a shared library, call it, libX that calls Foo::getBar() at
some point. And is linked during compile time to libfoo.
There is an application appfoo that opens libX via dlopen and
instantiates an FooObj from that library (using extern "C" function
create). appfoo destroys the instantiated object, closes libfoo with
dlclose and then later on opens it again with dlopen and creates a
new
instance of FooObj.
At this point appfoo segfaults with a weird stack trace, mayby
pointing to std::stringstream.

Appfoo instantiates N different plugins that all use libfoo.

What happens? This has to have something to do with the way GCC
creates/destroys the static variables or something like that.

Andrew Haley

unread,
Jan 16, 2012, 12:11:48 PM1/16/12
to
Markku Linnoskivi <markku.l...@gmail.com> wrote:

> Appfoo instantiates N different plugins that all use libfoo.
>
> What happens? This has to have something to do with the way GCC
> creates/destroys the static variables or something like that.

I wonder if this is a break of the one difinition rule. It'd help if
you could come up with a test case that we can run.

Andrew.

Markku Linnoskivi

unread,
Jan 17, 2012, 4:50:31 AM1/17/12
to
Hmm. It seems that the problem might have been caused by somthing
totally different. I tried to write similar code to reproduce it but
it worked fine. Allthough inline static behaviour is interesting. It
seems that the dll that is loaded last is the one that has it's code/
memory loaded and can cause some unwanted reslusts. My first attempt
was a function in the lines of:

static std::string func(const std::string& str)
{
return str;
}

And I called it from two distrinct DLL:s like func("foo1") and
func("foo2"). Both seemd to return "foo2". (The actual code was not
excatly that, but involeved the same kinda structure as in the
original post.) As I understand, what happens is the Dll2 code is
loaded in place of the previously loaded Dll1 code since the function
is the same as it ought to be since it's static.

I did some more tests and constructors in similar case (static func
with static object variables) get only called once as they should be.

So all in all, everything seems to work fine. (though I did my tests
with gcc 4.4.3 that is bit newer than the original compiler)

Andrew Haley

unread,
Jan 17, 2012, 6:06:18 AM1/17/12
to
Markku Linnoskivi <markku.l...@gmail.com> wrote:
> Hmm. It seems that the problem might have been caused by somthing
> totally different. I tried to write similar code to reproduce it but
> it worked fine.

Yes. That is one of the reasons thtat a test case is so useful. :-)

Andrew.
0 new messages