在不同的访问器中指定静态局部变量的构造/销毁顺序 [英] Specify construction/destruction order of static locals in different accessors

查看:244
本文介绍了在不同的访问器中指定静态局部变量的构造/销毁顺序的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我遇到了 cxa_finalize 运行程序崩溃(这是一个程序,而不是其中的库):

  $ ./ac-test.exe 
断言失败:AcLock.cpp(54):AcLock
libc ++ abi.dylib:terminate called没有活动异常
中止陷阱:6

断言/崩溃是由于交互在对象和记录器之间。记录器在对象之前被销毁,但对象使用记录器。因此,弹出assert或crash的互斥量已经被销毁(因此,锁定日志记录时 pthread_mutex_lock 失败的原因)。



我阅读了指定变量的属性的GCC手册

a>和声明函数的属性,但我显然缺少某些内容。



我将对象和记录器放置在访问器中的公共头中,并尝试指定构造顺序:

  // AcGlobals.h 
static AcLogger& GetLogger(){

static AcLogger logger __attribute __(init_priority(50));
return logger;
}
static AcSocketList& getAcceptSockets(){

static AcSocketList sockets __attribute __(init_priority(100));
return sockets;
}

这导致了一堆错误:



./ AcGlobals.h:24:46:error:expected';'在声明结束
static AcLogger logger __attribute __((init_priori ...

./AcGlobals.h:24:47:warning:声明不声明任何内容
[-Wmissing-declarations]
static Aclogger logger __attribute __((init_priori ...

我也试过将属性放在函数上,而不是变量:

  // AcGlobals.h 
static AcLogger& GetLogger()__attribute __(init_priority(50)){

static AcLogger logger ;
return logger;
}
static AcSocketList& GetAcceptSockets()__attribute __(init_priority(100)){

static AcSocketList socket;
return sockets;
}

这导致更多的问题:

  ./ AcGlobals.h:22:53:warning:GCC不允许在此
中的init_priority属性在函数定义[-Wgcc-compat] b $ b static AcLogger& GetLogger()__attribute __((init_priority(50))){
^
./AcGlobals.h:22:53:错误:只能使用文件范围的'init_priority'属性
定义对象类型



我也尝试了 __ attribute __((constructor(50) ))而不是 init_priority



em:我在一台苹果机上工作。苹果有一个特征,其中构造函数优先级只适用于同一文件中的装饰函数和变量。



如何精确地指定构建和销毁本地静态对象的顺序?

解决方案

这是一个经典的问题,当使用Meyers单例
(这基本上是你在做什么)。解决方案是
不是破坏单例;而不是静态局部
变量,您应该使用动态分配而不删除:

  static AcLogger& GetLogger()
{
static AcLogger * logger = new AcLogger;
return * logger;
}

请注意,在这种情况下,您必须确保每次使用
记录器刷新(但这通常是这种情况);
否则,您可能会遇到未刷新的数据。



关于您尝试使用
编译器的扩展功能:不太熟悉它,但我不明白你如何
可以使用在局部变量 init_priority 的东西。
局部静态
变量的构造(和销毁)时间由语言定义(在这种情况下,
销毁时间不是
你想要的) 。如果你想使用
这个非标准扩展,你可能必须使
实例变量成为一个静态类成员,或者甚至一个全局
(在这种情况下,你可以't使构造函数私有)。


I'm experiencing a crash in cxa_finalize running a program (this is a program, and not a library within):

$ ./ac-test.exe 
Assertion failed: AcLock.cpp(54): AcLock
libc++abi.dylib: terminate called without an active exception
Abort trap: 6

The assertion/crash is due to the interaction between an object and a logger. The logger is destructed before the object, but the object uses the logger. So the mutex being acquired that pops the assert or crash has already been destroyed (hence the reason pthread_mutex_lock fails when locking the logger).

I've read the GCC manual on Specifying Attributes of Variables and Declaring Attributes of Functions, but I'm obviously missing something.

I placed the object and logger in a common header within accessors and tried to specify a construction order:

// AcGlobals.h
static AcLogger& GetLogger() {

    static AcLogger logger __attribute__(init_priority(50));
    return logger;
}
static AcSocketList& GetAcceptSockets() {

    static AcSocketList sockets __attribute__(init_priority(100));
    return sockets;
}

That resulted in a bunch of errors:

./AcGlobals.h:24:46: error: expected ';' at end of declaration
    static AcLogger logger __attribute__((init_priori...

./AcGlobals.h:24:47: warning: declaration does not declare anything
      [-Wmissing-declarations]
    static AcLogger logger __attribute__((init_priori...

I also tried placing the attribute on the function rather than the variable:

// AcGlobals.h
static AcLogger& GetLogger() __attribute__(init_priority(50)) {

    static AcLogger logger;
    return logger;
}
static AcSocketList& GetAcceptSockets() __attribute__(init_priority(100)) {

    static AcSocketList sockets;
    return sockets;
}

This resulted in more problems:

./AcGlobals.h:22:53: warning: GCC does not allow init_priority attribute in this
      position on a function definition [-Wgcc-compat]
static AcLogger& GetLogger() __attribute__((init_priority(50))) {
                                              ^
./AcGlobals.h:22:53: error: can only use 'init_priority' attribute on file-scope
      definitions of objects of class type

I also tried __attribute__((constructor(50))) instead of init_priority with no joy.

Note: I'm working on an Apple machine. Apple has a 'feature' where constructor priority only applies to adorned functions and variables within the same file. So these cannot be spread out across translation units.

How, precisely, do I specify the order of construction and destruction of local static objects?

解决方案

This is a classical problem when using the Meyers singleton (which is basically what you're doing). The solution is to not destruct the singleton; instead of a static local variable, you should use dynamic allocation without a delete:

static  AcLogger& GetLogger()
{
    static AcLogger* logger = new AcLogger;
    return *logger;
}

Note that in this case, you will have to ensure that each use of the logger flushes (but this is usually the case anyway); otherwise, you may end up with unflushed data.

With regards to your attempt to use an extended feature of your compiler: I'm not too familiar with it, but I don't see how you can use something called init_priority on a local variable. The construction (and destruction) time of local static variables is defined by the language (and in this case, the destruction time is not what you want). If you want to use this non-standard extension, you'll probably have to make the instance variable a static class member, or maybe even a global (in which case, you can't make the constructor private).

这篇关于在不同的访问器中指定静态局部变量的构造/销毁顺序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆