在GNU维基上阅读Visibility,这是很清楚的.

以C++教程为例this

// classes example
#include <iostream>
using namespace std;

class Rectangle {
    int width, height;
  public:
    void set_values (int,int);
    int area() {return width*height;}
};

void Rectangle::set_values (int x, int y) {
  width = x;
  height = y;
}

有没有可能在不修改代码的情况下,将第一个链接中显示的area()个公开,set_values(int,int)个本地?

我写了我的makefile来获得.so

someproj.so : someproj.cpp
    g++ --std=c++11 -O3 -fPIC -shared someproj.cpp -o someproj.so

修改为通过添加-fvisibility=hidden隐藏所有符号

someproj.so : someproj.cpp
    g++ --std=c++11 -O3 -fvisibility=hidden -fPIC -shared someproj.cpp -o someproj.so

可以通过修改上面的编译命令来定制哪些函数是公开的吗?

目前正在使用gcc的4.7.2版本

推荐答案

是否可以通过修改上面的编译命令来定制公开哪些函数?

不,编译选项-fvisibility=[default|internal|hidden|protected]

是否可以在不改变代码的情况下,如第一个链接所示,将area()设置为公共并将_值(int,int)设置为本地?

也没有.

如何将源代码更改为Rectangle::area()动态

让我们从以下几点开始:

rectangle.cpp (1)

class Rectangle {
    int width, height;
  public:
    void set_values (int,int);
    int area() {return width*height;}

};

void Rectangle::set_values (int x, int y) {
  width = x;
  height = y;
}

只需将其编译成PIC rectangle.o即可:

$ g++ -Wall -c -fPIC rectangle.cpp

然后判断全局符号表:

$ nm -C rectangle.o
0000000000000000 T Rectangle::set_values(int, int)

请注意,Rectangle::area并不存在.这对我来说是不可用的

这是因为它在类定义中被定义为inline,并且从未被调用

另一方面,Rectangle::set_values不是内联定义的,因此编译器

要使Rectangle::area符合某种可见性类型,我们首先需要

rectangle.cpp (2)

class Rectangle {
    int width, height;
  public:
    void set_values (int,int);
    int area();

};

int Rectangle::area() {return width*height;}

void Rectangle::set_values (int x, int y) {
  width = x;
  height = y;
}

重新编译并再次判断全局符号表:

$ g++ -Wall -c -fPIC rectangle.cpp
$ nm -C rectangle.o
000000000000001a T Rectangle::set_values(int, int)
0000000000000000 T Rectangle::area()

好的现在,Rectangle::area的全球定义出现了.

接下来,让我们从rectangle.o创建一个共享库librectangle.so:

$ g++ -o librectangle.so --shared rectangle.o

以下是全球符号表中的Rectangle::*个符号:

$ nm -C librectangle.so | grep 'Rectangle::'
00000000000005d4 T Rectangle::set_values(int, int)
00000000000005ba T Rectangle::area()

下面是dynamic符号表中的Rectangle::*个符号:

$ nm -CD librectangle.so | grep 'Rectangle::'
00000000000005d4 T Rectangle::set_values(int, int)
00000000000005ba T Rectangle::area()

他们是一样的.

现在,让我们隐藏这些符号以进行动态链接.我们需要recompile rectangle.cpp

$ g++ -Wall -c -fPIC -fvisibility=hidden rectangle.cpp
$ g++ -o librectangle.so --shared rectangle.o

下面是全局符号表中的Rectangle::*个符号:

$ nm -C librectangle.so | grep 'Rectangle::'
0000000000000574 t Rectangle::set_values(int, int)
000000000000055a t Rectangle::area()

他们和以前一样.

下面是dynamic符号表中的Rectangle::*个符号:

$ nm -CD librectangle.so | grep 'Rectangle::'; echo Done
Done

现在有none个,多亏了-fvisibility=hidden个.

最后,让我们只动态显示Rectangle::area个,保持所有

rectangle.cpp (3)

class Rectangle {
    int width, height;
  public:
    void set_values (int,int);
    __attribute__((visibility("default"))) int area();

};

int Rectangle::area() {return width*height;}

void Rectangle::set_values (int x, int y) {
  width = x;
  height = y;
}

然后重新编译并重新链接:

$ g++ -Wall -c -fPIC -fvisibility=hidden rectangle.cpp
$ g++ -o librectangle.so --shared rectangle.o

全局符号表仍然显示:

$ nm -C librectangle.so | grep 'Rectangle::'
00000000000005a4 t Rectangle::set_values(int, int)
000000000000058a T Rectangle::area()

动态符号表仅显示:

$ nm -CD librectangle.so | grep 'Rectangle::'
000000000000058a T Rectangle::area()

Rectangle::area现在是共享库公开的唯一符号

And before you go...

还有一件事:

是否可以在不改变代码的情况下,如第一个链接所示,将area()设置为公共并将_值(int,int)设置为本地?

为动态链接隐藏符号并不等于local.动态可见性(默认|内部|隐藏|保护)

则符号不会出现在全局或动态符号表中.

Linux相关问答推荐

在shell 中使用排除模式的grep

将十六进制文件名转换为十进制

当 skylake 有 fsgsbase 时,为什么使用 __builtin_ia32_wrfsbase64 会收到非法指令?

在android上使用lldb-server进行lldb调试?

内核是如何工作的?

按主机名的 IPv6 地址

让 Tk 看起来像一个原生 Linux 应用程序

bash shell 脚本函数定义(如f () {})中使用的括号是什么?它与使用function关键字不同吗?

并行运行 shell 脚本

判断 VT-x 是否已激活而无需在 Linux 中重新启动?

如何在 Linux 上传递带感叹号的参数?

Supervisord - 将进程标准输出重定向到控制台

Linux 上真的没有异步块 I/O 吗?

解压tar tar.bz2 文件报错

cat、grep 和 cut - 翻译成 python

ngrok 如何在防火墙后工作?

将所有文件扩展名转换为小写

Anaconda 安装后,conda 命令失败并显示ImportError: no module named conda.cli

使用 SED 将单词的首字母大写

Linux(Ubuntu)终端-如何查看以前的页面不再可见