【问题标题】:When does dynamic initialization of static volatile variable happen?静态 volatile 变量的动态初始化何时发生?
【发布时间】:2020-01-27 09:30:05
【问题描述】:

首先,让我们看一下标准(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_ */

在 myfile.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 改变了游戏规则?

【问题讨论】:

  • 一旦main函数被调用,命名空间范围内的所有变量(包括全局命名空间)都应该已经被初始化了。
  • volatile 仅影响允许编译器优化对该变量的访问的方式。似乎不太可能对初始化顺序产生任何影响。
  • @Some 程序员老兄您指的是static volatile 变量还是命名空间范围内的任何变量?在后一种情况下,您的声明不符合标准所说的,即初始化可能被推迟?

标签: c++ static volatile static-initialization


【解决方案1】:

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

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

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

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

【讨论】:

  • 我在写这个问题时有一个例子,就像你在上一段中给出的那样。只是为了澄清一下,易失性对变量的初始化时间没有影响吗?这是正确的结论吗?如果是这样,我会接受你的回答。
  • 我相信是的。 “易失性”中的任何内容都不会影响必须进行初始化的时间。只有如何(直接写回内存)。对于“这个变量指向硬件并且可以在代码的控制之外进行更改”,C 并没有任何内容。 volatile 大部分都有效,但正如您所注意到的,初始化并不完美。
猜你喜欢
  • 1970-01-01
  • 2011-08-22
  • 2010-12-22
  • 1970-01-01
  • 1970-01-01
  • 2010-09-26
  • 2010-12-11
  • 1970-01-01
相关资源
最近更新 更多