我正在 Linux 和 gcc 上试验 C++ 符号可见性。似乎首选的方法是使用 -fvisibility=hidden,并根据 Visibility gcc wiki 页面 (http://gcc.gnu.org/wiki/Visibility) 一个接一个地导出使用的符号。 我的问题是 许多 库不能很好地处理这个问题,他们忘记显式导出符号,这是一个严重的问题。在修复了几个 bug 之后,甚至 boost 的某些部分仍然可能受到影响。当然这些错误应该被修复,但在此之前我想使用一种“安全”的方式来隐藏尽可能多的符号。
我想出了一个解决方案:我将所有符号放在一个命名空间中,并在其上使用符号隐藏属性并导出公共(public)接口(interface),这样只有我的符号会受到影响。
问题是,当我针对该库为每个尚未导出并在应用程序中用作类字段的类编译某些内容时,我收到了一条警告消息。
namespace MyDSO __attribute__ ((visibility ("hidden"))) {
struct Foo {
void bar() __attribute__ ((visibility ("default"))) {}
};
}
struct Bar {
MyDSO::Foo foo;
};
int main() {}
警告消息可以在这个小例子中重现,但命名空间当然应该在应用程序中其他类的库中。
$ gcc-4.7.1 namespace.cpp -o namespace
namespace.cpp:7:8: warning: ‘Bar’ declared with greater visibility than the type of its field ‘Bar::foo’ [-Wattributes]
据我了解符号可见性,隐藏命名空间应该与使用 -fvisibility=hidden 具有非常相似的效果,但使用后者时我从未收到类似的警告。我看到当我将 -fvisibility=hidden 传递给应用程序时,应用程序中的类也将被隐藏,所以我不会收到警告。但是当我不传递选项时, header 中的任何符号都不会被编译器隐藏,所以我不会再次收到警告。
此警告消息的建议是什么?这是一个严重的问题吗?在哪些情况下这会导致任何问题?隐藏命名空间与 fvisibility=hidden 有何不同?
最佳答案
在回答您的具体问题之前,我应该向其他阅读者提及,为每个命名空间应用符号可见性属性是 GCC 特有的功能。 MSVC 仅支持类、函数和变量的 dllexport,如果您希望代码可移植,则必须在此处匹配 MSVC。正如我最初的 GCC 符号可见性指南(您在 GCC 网站上链接的那个)所指出的,MSVC 基于宏的 dllexport 机制可以很容易地重用以在 GCC 上实现类似的功能,因此移植到 MSVC 将为您提供符号可见性处理“免费”。
关于您的具体问题,GCC 正确地警告您。如果外部用户尝试使用公共(public)类型 Bar,他们几乎肯定需要使用 Bar 中的所有内容,包括 Bar::foo。出于完全相同的原因,所有私有(private)成员函数,尽管是私有(private)的,都需要可见。很多人对此感到惊讶,认为私有(private)成员函数符号根据定义是任何人都无法访问的,但他们忘记了仅仅因为程序员没有访问权限并不意味着 编译器 '不需要需要访问。换句话说,私有(private)成员函数对您来说是私有(private)的,而不是编译器。如果它们出现在头文件中,则通常意味着编译器需要访问,即使在匿名命名空间中也是如此(这仅对程序员是匿名的,而不是倾向于使用内容的哈希作为“真实”命名空间名称的编译器)。
隐藏命名空间与 -fvisibility=hidden 的效果截然不同。这是因为 GCC 会喷出许多符号,超出特定类型的符号,例如对于 vtables,对于 type_info 等 -fvisibility=hidden 隐藏您无法通过任何编译器指示的方式隐藏的内容,并且将两个二进制文件加载到具有冲突符号的同一进程中绝对必要,例如使用不同版本的 Boost 构建的两个共享对象。
感谢您尝试解决由 ELF 中损坏的符号可见性引起的问题以及损坏的 C++ 二进制文件的后果以及程序员生产力的严重损失。但是您无法修复它们 - 它们是 ELF 本身的错误,它是为 C 而不是 C++ 设计的。如果有什么安慰的话,几个月前我写了一篇关于这个主题的内部 BlackBerry 白皮书,因为 ELF 符号可见性问题对于我们在 BB10 中和对于任何拥有重要 C++ 代码库的大公司来说都是一个问题。所以,也许你会看到一些针对 C++17 提出的解决方案,特别是如果 Doug Gregor 的 C++ Modules 实现取得了良好的进展。
关于c++ - 符号可见性和命名空间,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15560892/
我的瘦服务器配置了nginx,我的ROR应用程序正在它们上运行。在我发布代码更新时运行thinrestart会给我的应用程序带来一些停机时间。我试图弄清楚如何优雅地重启正在运行的Thin实例,但找不到好的解决方案。有没有人能做到这一点? 最佳答案 #Restartjustthethinserverdescribedbythatconfigsudothin-C/etc/thin/mysite.ymlrestartNginx将继续运行并代理请求。如果您将Nginx设置为使用多个上游服务器,例如server{listen80;server
我正在编写一个方法,它将在一个类中定义一个实例方法;类似于attr_accessor:classFoocustom_method(:foo)end我通过将custom_method函数添加到Module模块并使用define_method定义方法来实现它,效果很好。但我无法弄清楚如何考虑类(class)的可见性属性。例如,在下面的类中classFoocustom_method(:foo)privatecustom_method(:bar)end第一个生成的方法(foo)必须是公共(public)的,第二个(bar)必须是私有(private)的。我怎么做?或者,如何找到调用我的cust
当我在我的Rails应用程序根目录中运行rakedoc:app时,API文档是使用/doc/README_FOR_APP作为主页生成的。我想向该文件添加.rdoc扩展名,以便它在GitHub上正确呈现。更好的是,我想将它移动到应用程序根目录(/README.rdoc)。有没有办法通过修改包含的rake/rdoctask任务在我的Rakefile中执行此操作?是否有某个地方可以查找可以修改的主页文件的名称?还是我必须编写一个新的Rake任务?额外的问题:Rails应用程序的两个单独文件/README和/doc/README_FOR_APP背后的逻辑是什么?为什么不只有一个?
我没有找到太多关于如何执行此操作的信息,尽管有很多关于如何使用像这样的redirect_to将参数传递给重定向的建议:action=>'something',:controller=>'something'在我的应用程序中,我在路由文件中有以下内容match'profile'=>'User#show'我的表演Action是这样的defshow@user=User.find(params[:user])@title=@user.first_nameend重定向发生在同一个用户Controller中,就像这样defregister@title="Registration"@user=Use
如何将send与+=一起使用?a=20;a.send"+=",10undefinedmethod`+='for20:Fixnuma=20;a+=10=>30 最佳答案 恐怕你不能。+=不是方法,而是语法糖。参见http://www.ruby-doc.org/docs/ProgrammingRuby/html/tut_expressions.html它说Incommonwithmanyotherlanguages,Rubyhasasyntacticshortcut:a=a+2maybewrittenasa+=2.你能做的最好的事情是:
我们目前正在为ROR3.2开发自定义cms引擎。在这个过程中,我们希望成为我们的rails应用程序中的一等公民的几个类类型起源,这意味着它们应该驻留在应用程序的app文件夹下,它是插件。目前我们有以下类型:数据源数据类型查看我在app文件夹下创建了多个目录来保存这些:应用/数据源应用/数据类型应用/View更多类型将随之而来,我有点担心应用程序文件夹被这么多目录污染。因此,我想将它们移动到一个子目录/模块中,该子目录/模块包含cms定义的所有类型。所有类都应位于MyCms命名空间内,目录布局应如下所示:应用程序/my_cms/data_source应用程序/my_cms/data_ty
我正在尝试在Rails上安装ruby,到目前为止一切都已安装,但是当我尝试使用rakedb:create创建数据库时,我收到一个奇怪的错误:dyld:lazysymbolbindingfailed:Symbolnotfound:_mysql_get_client_infoReferencedfrom:/Library/Ruby/Gems/1.8/gems/mysql2-0.3.11/lib/mysql2/mysql2.bundleExpectedin:flatnamespacedyld:Symbolnotfound:_mysql_get_client_infoReferencedf
Rails中有没有一种方法可以提取与路由关联的HTTP动词?例如,给定这样的路线:将“users”匹配到:“users#show”,通过:[:get,:post]我能实现这样的目标吗?users_path.respond_to?(:get)(显然#respond_to不是正确的方法)我最接近的是通过执行以下操作,但它似乎并不令人满意。Rails.application.routes.routes.named_routes["users"].constraints[:request_method]#=>/^GET$/对于上下文,我有一个设置cookie然后执行redirect_to:ba
我对如何计算通过{%assignvar=0%}赋值的变量加一完全感到困惑。这应该是最简单的任务。到目前为止,这是我尝试过的:{%assignamount=0%}{%forvariantinproduct.variants%}{%assignamount=amount+1%}{%endfor%}Amount:{{amount}}结果总是0。也许我忽略了一些明显的东西。也许有更好的方法。我想要存档的只是获取运行的迭代次数。 最佳答案 因为{{incrementamount}}将输出您的变量值并且不会影响{%assign%}定义的变量,我
这是针对我无法破坏的现有公共(public)API,但我确实希望对其进行扩展。目前,该方法采用字符串或符号或任何其他在作为第一个参数传递给send时有意义的内容我想添加发送字符串、符号等列表的功能。我可以只使用is_a吗?数组,但还有其他发送列表的方法,这不是很像ruby。我将调用列表中的map,所以第一个倾向是使用respond_to?:map。但是字符串也会响应:map,所以这行不通。 最佳答案 如何将它们全部视为数组?String的行为与仅包含String的Array相同:deffoo(obj,arg)[*arg].eac