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

Posted

技术标签:

【中文标题】g++:在嵌入式应用程序中使用单例【英文标题】:g++: Using singleton in an embedded application 【发布时间】:2014-05-24 00:20:15 【问题描述】:

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

【问题讨论】:

您可以使用-S 查看汇编程序,以及两个版本之间的不同之处。 (有一点不同:在第一个版本中,编译器必须防止来自不同线程的多次调用,以仍然确保对象只初始化一次。但是我无法想象会占用这么多空间。) 在编译器无法使用线程安全原语(互斥锁)的嵌入式系统上,GCC 如何确保线程安全? 我不知道。也许它不支持这样的系统上的多线程。或者它本身也实现了某种机制(这可能会导致大小增加)。 【参考方案1】:

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

这是我的示例代码:

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/

【讨论】:

【参考方案2】:

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

【讨论】:

以上是关于g++:在嵌入式应用程序中使用单例的主要内容,如果未能解决你的问题,请参考以下文章

如何使用嵌入式 tomcat 会话集群设置 Spring Boot 应用程序?

单例核心数据管理器可用于所有 UINavigationController 嵌入式视图

在STM32F746G-DISCO开发板上使用Nabto + FreeRTOS的演示热泵应用

2014025689《嵌入式程序设计》第一周学习总结

Linux嵌入式驱动学习之路按键驱动-poll机制

如何使 junit 测试在 springboot 应用程序中使用嵌入式 mongoDB?