首页 > 解决方案 > 静态 volatile 变量的动态初始化何时发生?

问题描述

首先,让我们看一下标准(C++14 [basic.start.init] 3.6.3/4):

具有静态存储持续时间的非局部变量的动态初始化是否在 main 的第一条语句之前完成是实现定义的。如果初始化延迟到 main 的第一个语句之后的某个时间点,它应该发生在与要初始化的变量在同一翻译单元中定义的任何函数或变量的第一次 odr-use (3.2) 之前。

说明volatile符意味着可以从外部源修改变量。但是,当无法保证何时初始化时,可能会发生变量被外部修改,然后发生动态初始化的情况。或者当 volatile 关键字存在时,它的工作方式是否不同?

这是我正在谈论的一个示例:在 myfile.h

#ifndef MYFILE_H_
#define MYFILE_H_

int my_init ();

#endif /* MYFILE_H_ */

在我的文件.cpp

#include <myfile.h>
#include <iostream>

int my_init () {
    std::cout << "init" << std::endl;
    return 1;
}

static volatile int my_var  __attribute__((unused)) = my_init();

在 main.cpp

#include <myfile.h>
#include <iostream>

int main() {
    std::cout << "main" << std::endl; 

    // Let's assume first odr-use of my_var or my_init happens down here, maybe 
    // in a function from another translation unit.

    return 0;
}

想象一下 my_init 是一个将 my_var 设置为有效默认状态的函数,以防万一它不会在外部设置为另一个有效状态。因此,当 my_var 首先在外部修改它,但后来设置为默认状态时,就会出现问题。因此,问题是 my_var 何时初始化。正如上面的标准报价所暗示的那样,还是volatile改变了游戏规则?

标签: c++staticvolatilestatic-initialization

解决方案


如果初始化延迟到 main 的第一个语句之后的某个时间点,它应该发生在与要初始化的变量在同一翻译单元中定义的任何函数或变量的第一次 odr-use (3.2) 之前。

您说“可以从外部源进行修改”。但任何此类修改都将是对同一翻译单元中定义的变量(实际上是变量)的 odr 使用。

更重要的是,除非您在某处导出地址或具有修改地址的功能,否则外部源根本无法访问静态变量。两者都将在同一个翻译单元中。同样,初始化发生在使用之前。

我没有看到的唯一情况是当您声明变量 volatile 时,因为硬件会在代码控制之外更改它,例如计时器。但是你最好手动初始化硬件或者知道你的实现是做什么的。初始化的顺序和时间都很重要。


推荐阅读