警告:“可见性”属性被忽略-符号可见性-C ++ / gcc

Cha*_*how 4 c++ gcc shared-libraries

相关主题: 为什么const在C ++中表示内部链接而在C ++中却没有?

我正在关注GCC可见性Wiki,以将可见性添加到共享库中。

当我编译源文件时,它会生成警告

警告:“可见性”属性已忽略[-Wattributes]

这是我的代码:

// my_shared_lib.h
#if __GNUC__ >= 4
    #define DLL_API __attribute__((visibility("default")))
    #define DLL_LOCAL __attribute__((visibility("hidden")))
#else
    #define DLL_API 
    #define DLL_LOCAL
#endif
DLL_LOCAL const int my_local_var;
Run Code Online (Sandbox Code Playgroud)

编译时会产生以下警告:

my_shared_lib.h: 'visibility' attribute ignored [-Wattributes]
DLL_LOCAL const int my_local_var;
               ^
Run Code Online (Sandbox Code Playgroud)

这是整个建筑物的信息:

make all
Building file: ../src/my_shared_lib.cc
Invoking: Cross G++ Compiler
g++-mp-4.8 -O3 -Wall -c -fmessage-length=0 -std=c++11 -MMD -MP -MF"src/my_shared_lib.d" -MT"src/my_shared_lib.d" -o "src/my_shared_lib.o" "../src/my_shared_lib.cc"
my_shared_lib.h: 'visibility' attribute ignored [-Wattributes]
DLL_LOCAL const int my_local_var;
               ^
Finished building: ../src/my_shared_lib.cc
Run Code Online (Sandbox Code Playgroud)

谁能告诉我如何使此警告静音以及为什么发生此警告?

是不是因为const variablehidden默认?

PS。我正在使用g ++ 4.8

Pet*_*esh 5

您可以通过传递-Wno-attributes给编译来静默警告。

该警告之所以发生是因为,正如相关的问题和答案所提到的那样,C++除非const对象被明确标记为extern,否则它们会自动具有内部链接。即默认情况下它们是隐藏的。这样做的理由是鼓励将这些const值按原样(即以形式const int x = value;)放入头文件中。如果默认情况下它们是公共的,那么如果在多个文件.cpp.o文件中出现相同的变量,您将遭受多重链接问题,如果将它们放置在.h没有本地链接规则的文件中会发生这种情况。

您还应该看到警告/错误:

my_shared_lib.h:...: error: uninitialized const 'my_local_var' [-fpermissive]
Run Code Online (Sandbox Code Playgroud)

除非另有说明,否则这是错误的一种变化,因为const是隐式静态的。

您如何解决这个问题?

首先,使用const时,请在标头中正确使用C++

const int my_local_var = VALUE;
Run Code Online (Sandbox Code Playgroud)

如果要.hCC++代码之间共享此文件,则选择是:

  1. 不要这么做const-这实际上对C代码没有意义,并且会阻止您完成私有,在标头中声明并在.c文件中定义但不会在结果中暴露.so
  2. 使用#define-是的,这很丑陋,但这比使用constfor C代码在语义上更正确,因为它可以防止您因错误赋值而意外更改值。
  3. 在.h中将其声明为:

...

DLL_LOCAL extern const int my_local_var;
Run Code Online (Sandbox Code Playgroud)

然后在.cc/ .cpp文件中将其定义为:

 #include "my_shared_lib.h"

 const int my_local_var = 42;
Run Code Online (Sandbox Code Playgroud)

您需要添加,#include否则它不会得到,extern从而允许它公开以链接组成的.o文件,.so而不会使其.so本身公开。

因此,我们有了(在Mac上,但前提是相同的):

标头:

$ cat wodge.h

#define PRIVATE __attribute__((visibility("hidden")))
#define PUBLIC __attribute__((visibility("default")))

PRIVATE extern const int my_local_var;
int do_with_x(int x);
Run Code Online (Sandbox Code Playgroud)

第一个C++档案:

$ cat wodge.cc

#include "wodge.h"

int
do_with_x(int y)
{
    return my_local_var * y;
}
Run Code Online (Sandbox Code Playgroud)

第二个C++文件-值的定义:

$ cat wodge2.cc 
#include "wodge.h"

const int my_local_var = 42;
Run Code Online (Sandbox Code Playgroud)

编译并显示结果符号表:

$ g++-4.8 -c -O3 -Wall -o wodge.o wodge.cc
$ g++-4.8 -c -O3 -Wall -o wodge2.o wodge2.cc
$ g++-4.8 -shared -o foo.dylib *.o
$ nm foo.dylib
0000000000000fb0 T __Z9do_with_xi
0000000000000fbc s _my_local_var
                 U dyld_stub_binder
Run Code Online (Sandbox Code Playgroud)