[cfe-dev] strange behavior when compile with -fvisibility-inlines-hidden flag

Richard Smith via cfe-dev cfe-dev at lists.llvm.org
Wed Dec 2 16:11:57 PST 2015


On Wed, Dec 2, 2015 at 1:41 AM, Weitian Leung via cfe-dev <
cfe-dev at lists.llvm.org> wrote:

> Hi all,
>
> Consider the following code (full source code can be found in attachment)
>
> object.h
>
> #define _DESTRUCTOR_IN_HEADER
>
> class Object
> {
> public:
>     Object();
> #ifdef _DESTRUCTOR_IN_HEADER
>     ~Object()
>     {
>     }
> #else
>     ~Object();
> #endif
>
> private:
>     class Counter
>     {
>     public:
>         Counter()
>             : _count(0)
>         {
>             printf("Counter: %p %d\n", this, _count);
>         }
>
>         ~Counter()
>         {
>             printf("~Counter: %p %d\n", this, _count);
>         }
>
>         void operator++()    { ++_count; }
>         void operator--()    { --_count; }
>
>     private:
>         int _count;
>     };
>
>     class Foo
>     {
>     public:
>         Foo() { ++counter(); }
>         ~Foo() { --counter(); }
>
>     private:
>         Counter& counter()
>         {
>             static Counter s_counter;
>             return s_counter;
>         }
>
>
When you use -fvisibility-inlines-hidden, you give this function hidden
visibility, so each DSO gets its own copy of the function. We also give
each DSO its own copy of each inline function's static local variables.
Thus the Object::Object() constructor in your shared library increments one
counter, and the Object::~Object() destructor in your main binary
decrements a different counter.

GCC appears to not make the static local variable hidden when it makes the
surrounding function hidden. That makes sense, since
-fvisibility-inlines-hidden is supposed to not change the semantics of the
program unless you're comparing addresses of inline functions.

    } foo;
> };
>
> object.cpp
>
> #include "object.h"
>
> Object::Object()
> {
> }
>
> #ifndef _DESTRUCTOR_IN_HEADER
> Object::~Object()
> {
>
> }
> #endif
>
>
> Build the source to a shared library (compile with
> -fvisibility-inlines-hidden flag),
> uses in main (another module)
>
>     Object *obj = new Object;
>     delete obj;
>
> you may see the strange output when running
>
> Counter: 0x7f2ded933efc 0
> Counter: 0x6012d4 0
> ~Counter: 0x6012d4 -1
> ~Counter: 0x7f2ded933efc 1
>
>
> The Counter construct/destruct twice, the second one (Counter: 0x6012d4 0)
> construct from
>  delete obj > Object::Foo::~Foo() > Object::Foo::counter()
>
> when comment out the line *#define _DESTRUCTOR_IN_HEADER *or remove the
> *-fvisibility-inlines-hidden* flag, it works as expected
> remove the compile flag
>
> Counter: 0x6013a4 0
> ~Counter: 0x6013a4 0
>
> comment out #define _DESTRUCTOR_IN_HEADER
>
> Counter: 0x7f1eaa16629c 0
> ~Counter: 0x7f1eaa16629c 0
>
>
> A bit difference, as the address isn't the same (heap and stack)
>
> this code works with GCC (as least 5.2 as my test) with or without the
> -fvisibility-inlines-hidden
> flag, of course it works with MSVC too.
>
> I don't known is this a bug with the flag or because the silly code makes
> it (as when constructor and
> destructor defined in the same file, it works).
>
> It seems that my last post failed, seems no body answers me, so I repost
> again, sorry.
> If this is the wrong place, please let me know where to post, thanks.
>
>
> _______________________________________________
> cfe-dev mailing list
> cfe-dev at lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-dev/attachments/20151202/56cf690f/attachment.html>


More information about the cfe-dev mailing list