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
),防止链接器剥离内容。有趣的是,您是否可以告诉链接器保留这些特定的对象,但仍然删除其他未使用的代码。让我查一下,谢谢。我认为静态/匿名名称空间并不总是被调用,因此解决了这个问题。学习新东西总是很愉快:)