- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
(如果找不到通用的解决方案,只需要为 gcc 5.4 工作)
我有一个通用工厂,用于根据某些键(例如表示类名的字符串)构造对象。工厂必须允许注册在构造时可能不知道的类(因此我不能简单地显式注册类列表)。
作为注册这些键及其相关构造函数的方法,我有另一个“RegisterInFactory”(模板化)类。在每个类的源文件中,我在对应于该类的匿名 namespace 中构造一个对象。这样,一旦构建了全局对象,每个类就会自动注册到工厂。除了执行此初始注册任务之外,这些对象永远不会被使用或引用。
然而,当代码被编译成一个静态库,当那个库被链接到一个可执行文件时,这些静态对象永远不会被构造,所以这些类不会注册到工厂,工厂也不能创建任何东西.
我知道 -Wl,--whole-archive -lfoo
标志,它确实包括这些全局对象。但它也引入了很多“多重定义”错误。我知道还有另一个标志可以关闭多重定义错误,但如果没有这些错误,我感觉不舒服。我知道 -u symbolName
可以关闭这些多重定义错误中的特定符号名称(至少我认为它是这样做的)。但是,这些冗余函数实在太多了(主要来自 protobuf 类)。
有没有办法告诉编译器不要优化那些对象,而只优化那些对象,这样我就可以避免多重定义问题?是否有另一种我可以遵循的符合约束条件的模式? (特别是我不知道在编译时哪些类可以注册到工厂。)
简化示例代码:工厂.h:
template<Base>
class Factory{
...
template<Derived>
class RegisterInFactory{
RegisterInFactory(){
instance().regInFactory(derivedConstructorFunctional);
}
};
};
在 Derived.cpp 中:
namespace{ BaseFactory::RegisterInFactory<Derived> registerMe{"Derived"}; }
最后的说明:我在某种程度上很幸运,没有链接器标志,它们仍然被包括在内,但似乎发生的唯一方法是派生类“足够”复杂。或者如果我直接在链接的可执行文件中使用 Derived 类。我真的无法说出它为什么有效。
最佳答案
该问题与优化无关。而是链接器如何链接来自静态库的符号。
However, when the code is compiled into a static library, when that library is linked into an executable, these static objects never get constructed, so the classes don't register to the factory, and the factory can't create anything.
发生这种情况是因为没有其他内容引用该注册变量。因此,链接器不会从存档中提取符号的定义。
要告诉 Unix 链接器保留该注册变量,即使没有其他引用它,使用 -Wl,--undefined=<symbol>
链接到该静态库时的编译器开关:
-u symbol
--undefined=symbol
Force symbol to be entered in the output file as an undefined symbol. Doing this may, for example, trigger linking of additional modules from standard libraries.
-u
may be repeated with different option arguments to enter additional undefined symbols.
如果该注册变量具有“C”链接,则 <symbol>
是变量名。
对于 C++ 链接,您将需要使用 nm --defined-only <object-file>
查找损坏的名称.您可能还需要将该变量放入命名空间中,以便它具有外部链接。
例子:
[max@supernova:~/src/test] $ cat mylib.cc
#include <cstdio>
namespace mylib {
struct Register
{
Register() { std::printf("%s\n", __PRETTY_FUNCTION__); }
};
Register register_me;
}
[max@supernova:~/src/test] $ cat test.cc
#include <iostream>
int main() {
std::cout << "Hello, world!\n";
}
[max@supernova:~/src/test] $ make
mkdir /home/max/src/test/debug
g++ -c -o /home/max/src/test/debug/test.o -MD -MP -std=gnu++14 -march=native -pthread -W{all,extra,error,inline} -ggdb -fmessage-length=0 -Og test.cc
g++ -c -o /home/max/src/test/debug/mylib.o -MD -MP -std=gnu++14 -march=native -pthread -W{all,extra,error,inline} -ggdb -fmessage-length=0 -Og mylib.cc
ar rcsT /home/max/src/test/debug/libmylib.a /home/max/src/test/debug/mylib.o
g++ -o /home/max/src/test/debug/test -ggdb -pthread /home/max/src/test/debug/test.o /home/max/src/test/debug/libmylib.a
[max@supernova:~/src/test] $ ./debug/test
Hello, world! <-------- Missing output from mylib::register_me.
[max@supernova:~/src/test] $ nm --defined-only -C debug/mylib.o
0000000000000044 t _GLOBAL__sub_I__ZN5mylib11register_meE
0000000000000000 t __static_initialization_and_destruction_0(int, int)
0000000000000000 B mylib::register_me <-------- Need a mangled name for this.
0000000000000000 r mylib::Register::Register()::__PRETTY_FUNCTION__
[max@supernova:~/src/test] $ nm --defined-only debug/mylib.o
0000000000000044 t _GLOBAL__sub_I__ZN5mylib11register_meE
0000000000000000 t _Z41__static_initialization_and_destruction_0ii
0000000000000000 B _ZN5mylib11register_meE <-------- The mangled name for that.
0000000000000000 r _ZZN5mylib8RegisterC4EvE19__PRETTY_FUNCTION__
# Added -Wl,--undefined=_ZN5mylib11register_meE to Makefile.
[max@supernova:~/src/test] $ make
g++ -o /home/max/src/test/debug/test -ggdb -pthread -Wl,--undefined=_ZN5mylib11register_meE /home/max/src/test/debug/test.o /home/max/src/test/debug/libmylib.a
[max@supernova:~/src/test] $ ./debug/test
mylib::Register::Register() <-------- Output from mylib::register_me as expected.
Hello, world!
关于c++ - 有没有办法强制 C++ 编译器不优化静态库中的特定静态对象?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47186406/
我一直很难编辑我的 .htaccess 文件来一起做这三件事。我已经能够分别获得每个部分,但我只是不明白逻辑流程如何使它们全部工作。 这是我能够使用 bluehost support 上的演示进行整合
我制作的宏将模板工作簿保存为两个单独的文件。每个测试保存一个(位置 1、2、3 或 4),然后在另一个宏中使用每个测试的数据。第二个是保留用于备份的原始数据文件。现在的问题是每次我在每个位置运行测试并
我正在写一篇关于如何使用 OCaml 的模块系统而不是 Java 的 OO 系统(一个有趣的视角)的博客文章。我遇到了一些我不理解的关于强制的事情。下面是一个基本模块和两个包含它的模块: module
我有一段将被执行多次(5,000+)的代码,以及一个仅在第一次为真的 if 语句。我曾想过使用“FIRST”变量并每次都进行比较,但每次都检查它似乎是一种浪费,即使我知道它不需要。 bool FIRS
首先,我是 Perforce 的新手,我主要通过其文档进行学习。 因此,我们即将从 CVS 迁移到 Perforce,我最近学到了一个避免更改每个工作区的 P4CLIENT 的好方法,即在工作区根目录
我正在为一段代码编写测试,其中包含我试图涵盖的 IOException 捕获。 try/catch 看起来像这样: try { oos = new ObjectOutputStream(new
我正在尝试在新闻项目滚动之间添加延迟。我知道 $.each() 通过不等待动画完成来完成其工作,但我想知道如何制作它,以便一次向上滚动一个项目并等到最后一个动画完成后再继续在循环中。 $(functi
假设已经编写了一个方法,需要一个排序列表作为其输入之一。当然这将在代码中进行注释和记录,param 将被命名为“sortedList”,但如果有人忘记,则会出现错误。 有没有办法强制输入必须排序?我正
我正在尝试将传入请求重定向到 https://www.domain.com/和所有 https://www.domain.com/ {所有页面}并且没有什么麻烦。我试过的方法: 添加此行:Redire
我将如何实现以下内容: title_selection = raw_input("Please type in the number of your title and press Enter.\n%
我有一个登录表单,我需要强制关闭自动完成功能。我试过了 jquery: $('#login').attr("autocomplete", "off"); HTML: Javascript:docume
我想知道我应该怎么做才能强制从 dev 分支 merge 到我的 master 分支?使用“git merge dev”会导致很多冲突。但是,我不想单独处理它们。相反,我只是想使用我的 dev 分支中
当安装 Hl7.Fhir.DSTU2 和 Hl7.Fhir.R4 这两个 Nuget 包时,我们得到如下信息: DSTU2 包似乎在使用 Hl7.Fhir.Support.Poco 版本 3.4.0
我正在尝试让一个功能组件在 testFn 执行时强制重新渲染。我想使用状态来做到这一点(如果有更好的方法请说出来),这似乎成功地强制重新渲染但只有两次,然后什么都没有。 我构建了一个简单的演示来模拟这
默认情况下,g++ 似乎会省略未使用的类内定义方法的代码。示例 from my previous question : struct Foo { void bar() {} void baz(
我正在尝试使用 here 中介绍的技术使我的网站背景以比内容慢的速度滚动。我不希望背景固定,只希望更慢。 这是 HTML 的样子: .parallax { perspective: 1px;
我能找到的最相似的问题是 'how to create a row of scrollable text boxes or widgets in flutter inside a ListView?'
我有以下 eslint 配置: "object-curly-newline": ["error", { "ImportDeclaration": "never",
我正在使用 TinyMCE 插件并将 valid_elements 选项设置为: "a[href|target:_blank],strong/b,em/i,br,p,ul,ol,li" 即使没有列出数
您好,我想使用以下命令放置多行描述 p4 --field Description="MY CLN Header \\n my CLN complete description in two -thre
我是一名优秀的程序员,十分优秀!