根据
answer,我使用标志-fvisibility = hidden和建筑工具链中的命令条隐藏了共享库的大多数内部符号.但我发现一些符号,用作标准C容器的元素,不能隐藏.
例如,
/* example1.cpp */
#include <stdio.h>
#define MY_EXPORTS __attribute__((visibility("default")))
extern "C" {
MY_EXPORTS void* create();
MY_EXPORTS void dosth(void*, int i);
MY_EXPORTS void release(void*);
}
class Point {
public:
int x;
int y;
Point() {
x = -1;
y = -1;
}
Point(int x_, int y_) {
x = x_;
y = y_;
}
int X() const {return x;}
int Y() const {return y;}
};
class ABC {
Point pts[2];
public:
ABC() {
Point pt0(0,0), pt1(1,1);
pts[0] = pt0;
pts[1] = pt1;
}
int getx(int i) { return pts[i].x; }
int gety(int i) { return pts[i].y; }
};
MY_EXPORTS void* create()
{
return new ABC();
}
MY_EXPORTS void dosth(void* handle, int i)
{
ABC* p = (ABC*)handle;
printf("%d,%d\n", p->getx(i), p->gety(i));
}
MY_EXPORTS void release(void* handle)
{
ABC* p = (ABC*)handle;
delete p;
}
像这样编译example1.cpp
$g++ -fPIC -shared -fvisibility=hidden ../example1.cpp -o libexample.so
$strip -R .comment -R .note libexample.so
并命令nm -D libexample.so | grep Point什么都不返回.
然后我用std :: vector替换C数组,
/* example2.cpp */
#include <stdio.h>
#include <vector>
#define MY_EXPORTS __attribute__((visibility("default")))
extern "C" {
MY_EXPORTS void* create();
MY_EXPORTS void dosth(void*, int i);
MY_EXPORTS void release(void*);
}
using std::vector;
class Point {
public:
int x;
int y;
Point() {
x = -1;
y = -1;
}
Point(int x_, int y_) {
x = x_;
y = y_;
}
int X() const {return x;}
int Y() const {return y;}
};
class ABC {
vector<Point> pts;
public:
ABC() {
pts.push_back(Point(0,0));
pts.push_back(Point(1,1));
}
int getx(int i) { return pts[i].x; }
int gety(int i) { return pts[i].y; }
};
MY_EXPORTS void* create()
{
return new ABC();
}
MY_EXPORTS void dosth(void* handle, int i)
{
ABC* p = (ABC*)handle;
printf("%d,%d\n", p->getx(i), p->gety(i));
}
MY_EXPORTS void release(void* handle)
{
ABC* p = (ABC*)handle;
delete p;
}
我像这样编译了example2.cpp
$g++ -fPIC -shared -fvisibility=hidden ../example2.cpp -o libexample.so
$strip -R .comment -R .note libexample.so
并命令nm -D libexample.so | grep Point打印这样的东西
000000000000311c W _ZN9__gnu_cxx13new_allocatorI5PointE10deallocateEPS1_m
00000000000030be W _ZN9__gnu_cxx13new_allocatorI5PointE7destroyEPS1_
0000000000003236 W _ZN9__gnu_cxx13new_allocatorI5PointE8allocateEmPKv
0000000000002aba W _ZN9__gnu_cxx13new_allocatorI5PointE9constructEPS1_RKS1_
...
0000000000002dd2 W _ZNSt6vectorI5PointSaIS0_EE3endEv
0000000000002fde W _ZNSt6vectorI5PointSaIS0_EE5beginEv
0000000000002942 W _ZNSt6vectorI5PointSaIS0_EE9push_backERKS0_
似乎因为STL的分配器和向量是由模板实现的.但为什么这些信息无法隐藏?
我的编译器是gcc-4.6,os是LMDE MATE版.
最佳答案 这些是由STL模板机制创建的函数.这些名称的可见性受sTL的控制,因此您的代码不会影响它们是否可见.
目前尚不清楚您是否只想减少符号数量,或者您实际上想要隐藏共享库中的特定名称 – 例如,如果您有类MySecretObject,则要隐藏的不同于符号表包含数千个名字,它让我烦恼.
您可能会创建一个隐藏实际名称的包装类型,但是在某种程度上,如果您确实想要隐藏对象的存在,则需要修改STL以不公开它.当然,这也意味着您需要使用该特殊名称[尽管有时巧妙地使用宏可以避免这种情况].
没有简单/推荐的方法来避免STL导出某些符号.那将会发生.如果使用包装器类型,则可以控制它们的名称,但它实际上并不会更改导出的名称的数量或类型,只是更改要公开的名称.
如果您解释一下您对“我只想出口那些我想要出口的东西”的关注,我会很乐意扩展答案.
编辑:
我相信它会通过将对象包装在另一个类中来“隐藏”一个名称:
class HidePoint
{
public:
Point p;
};
现在,您当然会公开HidePoint,但如果您将其称为A或W或类似的东西,那么它就是隐藏的.
或者:
#define Point SomeOtherUniqueName
将隐藏名称.