简单地说:我想在程序退出时写入文件,所以我有一个接受文件名(char *)的对象和对Google Protobuf消息的引用(出于这些目的,你可以假装它是构造函数中的字符串&)然后将消息写入析构函数中的文件名。然后,在main()中,我初始化其中一个对象并将其声明为静态(因此当程序因任何原因退出时它将被破坏)。
我的代码在我改变某些东西(貌似)无关之前已经完美地进行了几次修改,现在它无法正常工作。现在,当对象析构时,char *和引用都指向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 << "debug\n";
//*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();
}
答案 0 :(得分:3)
您遇到问题的原因如下:
MathHelper::Log log
将在您的主要返回之前被破坏,但WriteOnShutdown
的析构函数将在主要返回后被称为。
由于WriteOnShutdown
在析构函数中使用对log
的引用,因此您正在访问“悬空”。引用,调用未定义的行为,从而看到问题。
你和filename
也有完全相同的问题。
明显的解决方法是将write
(从某种程度上说,由于多种原因,这是一个可怕的名称)从静态变为自动变量。
答案 1 :(得分:-1)
这称为http://dygraphs.com/date-formats.html(同样适用于析构函数)。这总是一个问题,你刚才碰巧幸运。
在您的情况下,一种简单的方法是将const char* filename;
更改为std::string &filename;
,将MathHelper::Log& message;
更改为MathHelper::Log message;
。这样,在析构函数被调用时,内存仍然存在。