c – 如果我将它用作STL容器的元素,为什么我不能隐藏某些符号的名称?

根据
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

将隐藏名称.

点赞