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

g++: Using singleton in an embedded application

本文关键字:singleton 应用程序 嵌入式 g++      更新时间:2023-10-16

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

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

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

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

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

-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("");
    }
}

参考文献:

  • http://gcc.gnu.org/onlinedocs/gcc/C_002b_002b-Dialect-Options.html
  • http://arkaitzj.wordpress.com/2009/11/07/static-locals-and-threadsafety-in-g/

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