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