【问题标题】:Global const variables not assigned when constructor is executed执行构造函数时未分配全局 const 变量
【发布时间】:2019-04-26 05:45:41
【问题描述】:

当我尝试在ProblemClass::ProblemClass() 中使用它时,没有分配MY_GLOBAL_CONST。为什么?如何解决?我正在处理一个旧的 VC6 MFC 项目。

SomeClass.h

#include "ProblemClass.h"
class SomeClass  
{
private:
    ProblemClass m_problemClass; //created on the heap

public:
    SomeClass();
    ~SomeClass();
}

ProblemClass.h

class ProblemClass
{
public:
    ProblemClass();
    ~ProblemClass();
}

ProblemClass.cpp

#include "ProblemClass.h"
const CString MY_GLOBAL_CONST = _T("User");//Also tried to put that line in ProblemClass.h without luck
ProblemClass::ProblemClass()
{
    CString foo = MY_GLOBAL_CONST; //MFC-Runtime assertion fails, MY_GLOBAL_CONST  is not assigned yet 
}
ProblemClass::~ProblemClass(){}

更新:

经过进一步调查,我可以确认 SomeClass 也在全局上下文中实例化。因此,Paul Sanders 说 “这里发生的是两个全局初始化程序以错误的顺序执行”是绝对正确的

【问题讨论】:

  • ProblemClass.cpp 以外的源文件中是否有ProblemClassSomeClass 类型的全局变量?不同翻译单元中全局变量的初始化顺序未定义。
  • 我没有在全球范围内使用这些类的实例。只有MY_GLOBAL_CONST 是全局的。到目前为止,SomeClass 只使用了一次,ProblemClass 只用在了SomeClass
  • 您何时何地使用SomeClass?请尝试创建minimal reproducible example 向我们展示。另外,如果您在调试器中捕获崩溃,调用堆栈是什么样的?
  • 应用程序很大。 SomeClass 出现在调用堆栈的早期,而 MY_GLOBAL_CONST 尚未分配。我们经常使用这些全局常量(在命名空间内)并且从来没有遇到过这样的问题。但是我们还没有在应用程序的启动中使用它们。至少在现代项目上,而不是我现在必须处理的 VC6 项目。稍后我将提供最小的示例。
  • 如果您在调用堆栈上没有看到mainWinMain,那么您实际上是在某处创建SomeClass 的实例作为全局变量或其成员。

标签: c++ constructor mfc visual-c++-6


【解决方案1】:

尝试替换:

const CString MY_GLOBAL_CONST = _T("User");

与:

const TCHAR MY_GLOBAL_CONST [] = _T("User");

后一种构造不需要任何运行时初始化,因此可以在其他初始化代码中依赖MY_GLOBAL_CONST(因为这里肯定会发生两个全局初始化程序以错误的顺序执行)。

【讨论】:

  • 我会尽快尝试一下!你的结论听起来很有道理。
  • 请注意,无论何时从MY_GLOBAL_CONST 创建CString 对象,这都会改变运行时行为。它不能再调用copy c'tor,需要重新计算长度。这意味着额外的运行时开销和损坏,以防 MY_GLOBAL_CONST 包含嵌入的 NUL 字符。
  • @IInspectable 在原始问题的上下文中,MY_GLOBAL_CONST 怎么可能包含 NUL 字符?
  • 问题是询问静态存储时长的对象的初始化顺序。未能初始化的对象的具体类型并不重要。但是,更改类型以解决问题会更改程序行为。如果你不觉得这是一个需要注意的重要细节,那就不要。我不在乎,但未来的访客可能会。
【解决方案2】:

我看起来您在声明中错过了 static 关键字。我需要在类外初始化的全局变量的秘诀。

头文件

class ProblemClass
{
public:
    ProblemClass();
    ~ProblemClass();

private:
    static const CString MY_GLOBAL_CONST; // declaration in the header file
}

源文件

const CString ProblemClass::MY_GLOBAL_CONST = _T("HELLO_WORLD"); // Initialization here outside of class

ProblemClass::ProblemClass()
{
    CString foo = MY_GLOBAL_CONST; //MFC-Runtime assertion fails, MY_GLOBAL_CONST  is not assigned yet 
}

// everything else

【讨论】:

  • 在示例中,MY_GLOBAL_CONST 不是ProblemClass 的成员。
  • @PeterRuderman OP 尝试将其作为会员,鉴于此,我采取了这种方式。没有提到全局不属于该类的要求。这只是一种方法。
  • 我非常清楚常量是类的一部分。但在这种情况下,我们使用全局变量。实际上它们被包装在命名空间中
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2010-12-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-03-29
相关资源
最近更新 更多