从静态变量引用非静态变量会使非静态变量先于静态变量进行析构函数
Referencing non-static variables from a static variable makes non-static variables destruct before static variable
简单地说:每当程序退出时,我都想写入一个文件,所以我在构造函数中有一个接受文件名(char*)和对Google Protobuf消息的引用的对象(出于这些目的,你可以假装它是一个字符串&),然后将消息写入析构函数中的文件名。然后,在main()中,我初始化其中一个对象,并将其声明为静态对象(因此,当程序出于任何原因退出时,它都会销毁)。
在我更改了一些(看似)无关的内容之前,我的代码在几次修订中都运行得很好,现在它不起作用了。现在,当对象析构函数时,char*和reference都指向char和Message的未集成版本。我有下面的相关代码:
using namespace std;
class WriteOnShutdown {
private:
const char* filename;
public:
MathHelper::Log& message;
WriteOnShutdown(char* a, MathHelper::Log& b) : filename(a), message(b) {}
~WriteOnShutdown() {
cout << "debugn";
//*filename is -52 (unitialised char)
//READ ACCESS VIOLATION - message is still valid, but message.DebugString tries to call a pointer which hasn't been initialised yet
cout << message.DebugString() << endl;
}
};
int main() {
char filename[100];
MathHelper::Log log;
//Initialise filename and log
static WriteOnShutdown write(filename, log);
//Do program stuff here
//Then, at the end of main(), printing write.message.DebugString() works like a charm
cout << endl << write.message.DebugString();
_getch();
}
出现问题的原因如下:
MathHelper::Log log
将在您的main返回之前被析构函数,但在main返回之后,WriteOnShutdown
的析构函数将被调用。
由于WriteOnShutdown
在析构函数中使用对log
的引用,因此您正在访问一个"悬空"引用,调用未定义的行为,从而发现问题。
filename
也有同样的问题。
显而易见的解决方案是将write
(顺便说一句,由于多种原因,它对对象来说是一个糟糕的名称)从静态更改为自动变量。
这被称为静态初始化顺序惨败(同样适用于析构函数)。这一直是个问题,你只是碰巧早些时候运气好。
在您的情况下,解决此问题的一个简单方法是将const char* filename;
更改为std::string &filename;
,将MathHelper::Log& message;
更改为MathHelper::Log message;
。这样,当析构函数被调用时,内存仍然存在。
相关文章:
- 在 .h 文件中的类中声明静态变量和在.cpp文件中声明"global"变量有什么区别
- 模板基类中的静态变量
- 类和静态变量
- 不同作用域中的静态变量和全局变量
- 静态变量声明和定义
- 是否可以依赖函数范围的静态变量来执行程序关闭期间调用的方法?
- 在类中继承静态变量?
- "local scope"中的 C++ 初始化静态变量
- 使用静态变量的递归调用的不同输出
- 复制文件流C++静态变量
- 跨模板化函数编译的静态变量
- C++编译器是否优化了顺序静态变量读取?
- C++,每个循环初始化一个新的静态变量
- (为什么)我们可以在初始化中将非静态类成员分配给静态变量吗?
- 这些语句是否等效(静态变量、常量变量和泛型)
- 程序如何知道静态变量是否需要初始化?
- 类外的静态变量实例化
- 无法解析静态变量
- 函数局部静态变量:从性能角度来看的优点/缺点
- 访问从 CPP 文件到其他头文件的静态变量