静态成员和分离线程本身的释放顺序

deallocation order of the static member and detached thread itself

有一个初始化和清理一些资源的全局函数。
但是当没有其他线程是 运行 时必须调用这两个函数。(比如 curl_global_init
Initializer必须手动调用,但我不想手动调用cleaner
所以我做了以下。

class GLOBAL_WRAPPER {
 public:
  static void init() {
    getInstance();
  }

  static GLOBAL_WRAPPER& getInstance() {
    static GLOBAL_WRAPPER inst;
    return inst;
  }

 private:
  GLOBAL_WRAPPER() {
    // do global init call
  }
  ~GLOBAL_WRAPPER() {
    // do global cleanup call
  }
};

void GLOBAL_INIT() {
  GLOBAL_WRAPPER::init();
}



int main(){
  GLOBAL_INIT();

  // do whatever you want

  // std::thread([](){for(;;);}).detach(); oops!
}

但是在这样糟糕的情况下:创建分离线程并且在 main 结束之前不终止它,什么时候调用静态变量的释放(GLOBAL_WRAPPER 在这种情况下)?

  1. 分离的线程终止并释放静态变量
  2. 释放静态变量并终止分离的线程
  3. 实现已定义。

我只对 线程 本身感兴趣,而不是线程存储持续时间对象。

C++ 标准指定(用这么多字)从 main 返回等同于调用 std::exit.

main function [basic.start.main]

A return statement in main has the effect of leaving the main function (destroying any objects with automatic storage duration) and calling std::exit with the return value as the argument. If control flows off the end of the compound-statement of main, the effect is equivalent to a return with operand 0.

exit定义如下(无关细节省略):

Startup and termination [support.start.term]

[[noreturn]] void exit(int status);

Effects:

— First, objects with thread storage duration and associated with the current thread are destroyed. Next, objects with static storage duration are destroyed and functions registered by calling atexit are called.

— Next, all open C streams ... are removed.

— Finally, control is returned to the host environment. If status is zero or EXIT_SUCCESS, an implementation-defined form of the status successful termination is returned. If status is EXIT_- FAILURE, an implementation-defined form of the status unsuccessful termination is returned.

未定义当主执行线程returns时非主执行线程运行会发生什么。所示代码不保证非主执行线程terminates/sequenced在mainreturns.

之前

因此,标准唯一规定的是:

  1. 全局对象被销毁

  2. “控制返回到主机环境”,a.k.a。:“它死了,吉姆”。

标准没有定义如果非主执行线程运行当主执行线程returns时会发生什么。 A.k.a.: 未定义的行为。