C++全局变量的生命周期

发布于 2024-10-31 07:10:05 字数 294 浏览 4 评论 0原文

我有一个全局变量,它是一个类的实例。此类在其构造函数 (directX) 中创建了一个图像。

问题是我在运行时遇到访问冲突,但代码可以编译。我认为问题在于类构造函数在 winmain 函数中完成初始化之前被调用。

所以我想知道的是

  1. 有没有人遇到过这个问题并且知道解决方案。

  2. 全局变量的生命周期是多少,我知道函数中声明的变量在返回后会丢失,并且编译器会检查代码以查看所有内容是否匹配,这就是为什么我们必须对函数进行原型设计,但是全局变量在哪里出现方程。

I have a global variable which is an instance of a class. This class created an image in its constructor (directX).

The problem is that I am getting an access violation at runtime but the code compiles. I think the problem is that the class constructor is being called before the initialisation done in the winmain function.

so what I want to know is

  1. has anyone encountered this problem and knows of a solution.

  2. What is the lifespan of a global, i know variables declared in a function are lost after it returns and that the compiler looks through the code the see if everything matches which is why we have to prototype functions but where do global's come into the equation.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

我家小可爱 2024-11-07 07:10:05

如果您确实想要一个全局的,可以在初始化完成后进行初始化(本质上,图像将在您第一次引用它时构建,之后您将使用预先构建的版本)。

全局变量是在调用 winmain 之前构建的(以未定义的顺序)。它们会一直留在那里,直到您的程序退出(此时我相信析构函数以未定义的顺序调用)。

您可以使用的另一个(可能更简单)替代方案是将全局从类的实例更改为指向它的指针...然后你会得到类似的东西:

// global...
MyGlobalClass *bigGlobalImageHolder;

// Winmain
// Perform directX setup (don't know what that is)
// Create the image class
bigGlobalImageHolder = new MyGlobalClass();


// do the rest of your stuff...  I'm guessing enter some kind of event loop

// clean up your global
delete bigGlobalImageHolder;
// exit your winmain (and application)

然后你当前引用全局的任何地方,你都可以通过指针引用它..

 // so
 bigGlobalImageHolder.GetImage();
 // becomes
 bigGlobalImageHolder->GetImage();

You probably want to look at something like the singleton pattern if you really want to have one instance of a global, that can be initialized after the initialisation is done (essentially, the image would be constructed the first time you referenced it after which you'd use the pre-constructed version).

Globals are constructed (in undefined order), before your winmain is called. They stay there until your program exits (at which point I believe the destructors are called in an undefined order)..

Another (possibly simpler) alternative you could use would be to change your global from an instance of the class to a pointer to it... then you'd have something like:

// global...
MyGlobalClass *bigGlobalImageHolder;

// Winmain
// Perform directX setup (don't know what that is)
// Create the image class
bigGlobalImageHolder = new MyGlobalClass();


// do the rest of your stuff...  I'm guessing enter some kind of event loop

// clean up your global
delete bigGlobalImageHolder;
// exit your winmain (and application)

Then everywhere you're currently referencing your global, you could reference it via a pointer instead..

 // so
 bigGlobalImageHolder.GetImage();
 // becomes
 bigGlobalImageHolder->GetImage();
疯了 2024-11-07 07:10:05

看来您正在经历“静态初始化顺序惨败”。

检查此以及以下常见问题解答。

正如上面已经提到的,您可能想要实现一种或另一种Singleton

It appears you are experiencing the "static initialization order fiasco".

Check this this and the following faqs.

As already mentioned above, you'll probably want to implement one or another kind of Singleton.

笔芯 2024-11-07 07:10:05
  1. 我曾经遇到过这个问题;无论类构造函数中使用什么代码,都应该在类构造函数启动之前进行初始化。假设如果其他变量也是全局变量,那么应该首先调用它们的构造函数。尽管全局变量的构造函数以未定义的方式调用,但您可以使用的唯一解决方法是,按照从最不依赖到最依赖的顺序在同一文件中定义依赖的全局变量。
  2. 全局寿命等于您的程序寿命
  1. I have faced this problem; Whatever code is used in that class constructor should be initialized before the class constructor starts. Suppose if the other variables are also globals then their constructor should be called first. Though constructors for global variables are called in undefined way, only small work around you can use is, define the dependent global variables in same files in order from least dependent to most dependent.
  2. Global lifespan is equal to your program lifespan
烟酉 2024-11-07 07:10:05

全局静态数据的生命周期是应用程序的生命周期。但是,在正常终止时,析构函数将运行。

这样做的问题是初始化/销毁发生的顺序并不总是确定的,并且当然不是可移植的(即取决于平台和运行时链接器)。

共享对象(动态链接)的情况最糟糕。一些平台允许使用链接器标志来指定共享对象的“优先级”(以便可以影响静态初始化顺序);其他平台(例如 AIX gcc、HP/UX)需要特殊的编译器属性来将静态过程标记为“dll 初始化例程”。


简而言之:不依赖静态数据,除非通过访问器函数。访问器函数可能如下所示:

 static int _myinternalvar = 3;
 static int GetMyInternalVar()
 {
      return _myinternalvar;
 }

这样,您确定知道静态变量在函数执行之前已初始化。如果访问器是唯一可以访问数据的函数,您可以在其范围内声明静态(添加封装)。

The lifetime of global statical data is for the lifetime of the application. However, on normal termination, destructors will run.

The problem with this is that the order in which initialization/destruction take place is not always deterministic, and certainly isn't portable (i.e. depends on platform and e.g. runtime linkers).

The situation is worst with shared object (dynamic linking). Some platforms allow to use linker flags to specify 'priorities' for shared objects (so that the static initialization order can be influenced); Other platforms (e.g. AIX gcc, HP/UX) require special compiler attributes to mark static procedures as 'dll initialization routines'.


In short: do not depend on statical data, except through accessor functions. An accessor function might look like this:

 static int _myinternalvar = 3;
 static int GetMyInternalVar()
 {
      return _myinternalvar;
 }

this way, you will know for sure that the static was initialized before the function is executed. It the accessor is the only function that can access the data, you can declare the static within it's scope (adding encapsulation).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文