4

我正在使用 C++ 中的 GNU ARM 工具链中的 GCC 4.8 为 Cortex M3 开发嵌入式应用程序。该应用程序使用一些通过函数局部静态变量实例化的单例,例如(真实代码):

GlobalDataTypeRegistry& GlobalDataTypeRegistry::instance()
{
    static GlobalDataTypeRegistry inst;
    return inst;
}

这是在 C++ 中实现单例的经典方法。问题是,一旦我使用这种实例化,输出代码大小就会爆炸,这显然意味着编译器/链接器添加了一些服务代码以正确初始化/销毁单例对象。

这是允许重现问题的最小示例:

这将编译成66k的代码(-Os):

struct A
{
    A()  { __asm volatile ("nop"); }
    ~A() { __asm volatile ("nop"); }
};

A& getA()
{
    static A a;
    return a;
}

int main()
{
    (void)getA();
    return 0;
}

这将编译成9k的代码(-Os):

struct A
{
    A()  { __asm volatile ("nop"); }
    ~A() { __asm volatile ("nop"); }
};

static A a;  // Extracted from the function scope
A& getA()
{
    return a;
}

int main()
{
    (void)getA();
    return 0;
}

如果该行(void)getA();被完全注释掉,最终的二进制大小将大约为4k

问题是:除了将静态变量从函数范围中提取出来之外,我还有哪些选项可以避免这个单例的额外 62k 代码?是否有任何选项可以告诉 GCC 在应用程序退出时不需要调用单例的析构函数(因为它永远不会退出)?还有其他优化方法吗?

4

2 回答 2

2

您可以在使用std::aligned_storage实现的缓冲区内创建带有放置 new 的单例。

于 2014-04-10T10:42:33.037 回答
2

为命令添加-fno-threadsafe-statics选项g++,您的代码大小将减少。

这是我的示例代码:

class X {
private: 
    X() { };

public:
    ~X() { };

    static X* get_instance() {
        static X instance;
        return &instance;
    }

    void show() {
        asm("");
    }
};


int main() {
    X* temp = X::get_instance();
    temp->show();

    while (true) {
        asm("");
    }
}

参考:

于 2014-04-13T14:46:38.733 回答