C++ 错误地删除死代码
我认为这是C++ 错误地删除死代码,c++,macos,linker,clang++,dead-code,C++,Macos,Linker,Clang++,Dead Code,我认为这是clang或OSX链接器中的一个bug,但我想在这里询问以确保 我在C++程序中有以下(简化)设置。单例存储库类: class Repository { public: static Repository *instance(); void registerWidget(const char *name, Widget *w) {} }; 小部件界面: class Widget { public: virtual void widgetify() = 0; }
clang
或OSX链接器中的一个bug,但我想在这里询问以确保
<>我在C++程序中有以下(简化)设置。单例存储库类:
class Repository {
public:
static Repository *instance();
void registerWidget(const char *name, Widget *w) {}
};
小部件界面:
class Widget {
public:
virtual void widgetify() = 0;
};
最后是一个简单的小部件:
class SimpleWidget : public Widget {
public:
virtual void widgetify() {}
};
在SimpleWidget
内部,我想在运行时自动将小部件注册到存储库中。通常我使用一个匿名名称空间和一个register函数来实现这一点。大概是这样的:
namespace {
bool registrar() {
Registrar::instance() -> registerWidget("SimpleWidget", new SimpleWidget);
return true;
}
bool R = registrar();
}
在当前使用Qt
以iOS和Android为目标的项目中,我遇到了这个系统的问题clang
(或链接器)正在将SimpleWidget
识别为死代码并将其剥离(因此它不会出现在存储库中,因为Registrator()
从未被调用)。尽管SimpleWidget
中显然引用了Registrator()
,但它似乎是这样做的。如果我在我的任何其他翻译单元中引用了SimpleWidget
,那么SimpleWidget
就不再被剥离,一切都正常工作
我是否遗漏了一些关于死代码剥离应该如何工作的内容,或者这是一个合法的工具链错误?在第一次调用该翻译单元(.cpp文件)中的函数之前,需要创建翻译单元(如R)中的所有对象。您的TU中没有对单个函数的调用,因此不需要创建R
,因此register()
确实是死代码,并且仅从register()
调用的任何东西都同样是死代码
工具链是正确的。您能否修改您的简单示例,使其实际可编译?根据您的实现方式,可能存在未定义的行为。这是否偶然涉及到静态库?@Wintermute,是的。虽然RealStand和SimuleWiGET在同一个静态库中,但翻译单元外部对翻译单元的任何引用都是来自C++启动工具的隐式调用。这通常不会阻止单元被剥离——这不是一个bug。您可能需要一些链接器标志来防止剥离。您可以使用--whole archive
(或者-Wl,--whole archive
,如果您通过编译器调用ld
),防止链接器剥离内容。有趣的是,您是否可以告诉链接器保留这些特定的对象,但仍然删除其他未使用的代码。让我查一下,谢谢。我认为静态/匿名名称空间并不总是被调用,因此解决了这个问题。学习新东西总是很愉快:)