0

我对在 xcode 4.6 中隐藏符号有一点问题或误解。我在网上到处搜索,找不到任何有相同问题的帖子。

目前我已经创建了一个框架项目,其中包含一个简单的头文件,其中包含:

class Test
{
public:

    Test(){}
    Test(){}
};

int a(int n) {return n;}

__attribute__((visibility("hidden"))) int b(int n) {return n;}

__attribute__((visibility("default"))) int c(int n) {return n;}

class X
{
public:
    virtual ~X();
};

class __attribute__((visibility("hidden"))) Y
{
public:
    virtual ~Y();
};

class __attribute__((visibility("default"))) Z
{
public:
    virtual ~Z();
};

X::~X() { }
Y::~Y() { }
Z::~Z() { }

在项目设置中,我确保将“默认隐藏的符号”切换为“是”,因此只有函数 int c 和 z 类将被导出或对其他项目可见。

我构建了没有错误或警告的框架,然后将其复制/添加到可可应用程序中进行测试。

我能够包含头文件,但我仍然能够访问所有类和函数。

我希望有人能解释我为什么或哪里出错或以前遇到过这个问题?

问候

4

1 回答 1

1

您的问题是,您在头文件中声明所有内容。这意味着即使未导出符号,当您将头文件导入另一个文件时,这些符号也会在您导入头文件的项目中重新创建,因此它们当然在该项目中可用。

我试图通过一个更简单的示例向您解释这一点。假设您有两个文件,MyLib.h 和 MyLib.c。

MyLib.h:

int add(int a, int b);

MyLib.c:

int add(int a, int b) { return a + b };

如果您现在提供add可见hidden性并将所有内容编译到库 ( MyLib) 中,则该库将没有符号 for add(因为它是隐藏的)。结果,如果你包含MyLib.h到另一个文件中,调用那里的add函数并最终链接这个文件MyLib,你会得到一个链接器错误,因为链接器会抱怨它找不到一个实现add(它只有一个声明来自 H 文件)。

但是,如果您将函数打包到标头本身中,那么 MyLib.h 是:

int add(int a, int b) { return a + b };

并且您提供addhidden可见性,该库也将没有符号add,但是当您将标头包含到另一个文件中时,此标头将add在导入它的文件中创建一个符号,因此您当然不会收到链接器错误并且能够打电话add

导入 H 文件只是将 H 文件的全部内容复制到找到导入指令的位置。现在考虑一下:如果您将问题中 H 文件的全部内容复制到包含它的文件的顶部,那么在当前项目中声明的所有符号当然都是可见和可用的。为什么它们不可见或不可用?它们不在库中,是的,但它们在标头中,因此在编译其他项目时会被编译。

应该在当前项目之外不可见的符号(“隐藏”符号)永远不应出现在框架的任何公共头文件中。为什么要宣布头文件中存在无论如何都不能使用的符号?实际上,在大多数情况下,不暴露头文件中的符号已经足以阻止人们使用它们。不导出它们的原因只是如果符号存在,则可以使用它,即使它没有被任何头文件公开(因此您只需要编写自己的头文件或external直接在代码中将其声明为符号)。因此,隐藏符号只是一种保障措施,以确保它在任何情况下都无法使用。

于 2013-02-19T13:16:03.547 回答