g ++:在嵌入式应用程序中使用单例

时间:2014-04-10 10:36:07

标签: c++ gcc embedded singleton gnu-arm

我正在用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在应用程序退出时没有必要调用单例的析构函数(因为它永远不会退出)?还有其他任何优化方法吗?

2 个答案:

答案 0 :(得分:2)

您可以在使用std::aligned_storage实现的缓冲区内创建包含new的单例。

答案 1 :(得分: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("");
    }
}

参考文献: