[Bug c++/62280] New: Symbols visibility not equivalent to class visibility (-fvisibility=hidden)
mathieu.malaterre at gmail dot com
gcc-bugzilla@gcc.gnu.org
Wed Aug 27 09:13:00 GMT 2014
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=62280
Bug ID: 62280
Summary: Symbols visibility not equivalent to class visibility
(-fvisibility=hidden)
Product: gcc
Version: 4.9.1
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: c++
Assignee: unassigned at gcc dot gnu.org
Reporter: mathieu.malaterre at gmail dot com
I am trying to compile a project that is written in portable C++. It does
compile fine with Visual Studio 2010 on Windows 7 and makes uses of symbol
visibilty macros.
However when I compile this project with gcc-4.7/gcc-4.9.1 on linux, I am
getting this linker error:
g++ -fvisibility=hidden -fvisibility-inlines-hidden [...]
/tmp/ccegevbt.o:(.rodata._ZTI12subclass[_ZTI12subclass]+0x10): undefined
reference to `typeinfo for ns::baseclass'
I did read a [previous report][1] and indeed exporting at class level directly
(instead of per symbol) solves the symptoms:
class __attribute__ ((visibility ("default"))) baseclass {
However the code is actually written to export only some member function, so it
should produce identical behavior with Visual Studio C++ compiler, right ?
class baseclass {
public: // Member functions
DLL_EXPORT baseclass();
DLL_EXPORT virtual ~baseclass();
My question: is what slightly different behavior in exporting symbols is
happening in between Visual Studio 2010 and gcc-4.7 ? How do I track which
symbol is actually causing issue ?
For clarification here is a very small toy example which works fine on Visual
Studio 2010
$ cat test.h
#pragma once
#ifdef __GNUC__
#define DLL_EXPORT __attribute__((visibility("default")))
#else
#define DLL_EXPORT __declspec(dllexport)
#endif
struct Base
{
DLL_EXPORT virtual ~Base();
DLL_EXPORT virtual Base* clone() {
return 0;
}
};
#undef DLL_EXPORT
and
$ cat test.cpp
#include "test.h"
Base::~Base()
{
}
and
$ cat main.cpp
#include "test.h"
struct Foo : public Base
{
virtual ~Foo();
virtual Base* clone() {
return new Foo();
}
};
Foo::~Foo()
{
}
int main()
{
Base* f = new Foo();
f->clone();
return 0;
}
using cmake, it is simply:
$ cat CMakeLists.txt
cmake_minimum_required(VERSION 2.8)
project(bla)
add_library(test SHARED test.cpp)
add_executable(main main.cpp)
target_link_libraries(main test)
>From linux:
$ export CXXFLAGS="-fvisibility=hidden -fvisibility-inlines-hidden"
$ cmake . && make
>From windows:
$ cmake . -G"NMake Makefiles"
$ nmake
For people not using cmake, you could use:
$ cat Makefile
main: main.cpp test.h libtest.so
g++ -fvisibility=hidden -fvisibility-inlines-hidden -L. -ltest main.cpp
-o main
libtest.so: test.cpp test.h
g++ -fvisibility=hidden -fvisibility-inlines-hidden -fPIC -shared
test.cpp -o libtest.so
which leads to:
$ make
g++ -fvisibility=hidden -fvisibility-inlines-hidden -fPIC -shared test.cpp
-o libtest.so
g++ -fvisibility=hidden -fvisibility-inlines-hidden -L. -ltest main.cpp -o
main
/tmp/cc5lGsdn.o: In function `Base::Base()':
main.cpp:(.text._ZN4BaseC2Ev[_ZN4BaseC5Ev]+0xf): undefined reference to
`vtable for Base'
/tmp/cc5lGsdn.o:(.rodata._ZTI3Foo[_ZTI3Foo]+0x10): undefined reference to
`typeinfo for Base'
collect2: error: ld returned 1 exit status
make: *** [main] Error 1
In case this matter, adding `-fno-devirtualize` does not help (as per sug from
[here][2])
Of course the obvious solution of changing:
struct Base
into
struct DLL_EXPORT Base
does solve the symptoms.
ref:
http://stackoverflow.com/questions/25522229/tracking-an-issue-with-fvisibility-hidden-that-triggers-a-undefined-reference-t
More information about the Gcc-bugs
mailing list