随机定义指针会使程序崩溃
Defining a pointer randomly crashes the program
在 class 中定义变量会导致应用程序执行期间发生随机崩溃。
调试模式下不会出现崩溃,只会在发布版本中出现。
它也发生在不同的执行点。我在执行过程中时不时地输出日志,它们会时不时地不同。
问题中的class是继承链中的中间一个:
class Base
{
public:
virtual ~BaseClass() { }
// Quite a few virtual methods declared here.
};
class Middle : public Base
{
public:
virtual ~Middle() { }
protected:
Middle(const std::string& name)
: _name(name)
, _db(Context::DbInstance())
{
}
/**
* Commenting out any of the following crashes or does not.
*/
// CareTaker* _careTaker; // 4 bytes, crashes.
// void* dummy; // 4 bytes, crashes.
// int dummy; // 4 bytes, crashes.
// short dummy; // 2 bytes, crashes.
// class Dummy {}; // 1 bytes, does not crash.
// // 0 bytes, member removed, does not crash.
std::string _name;
// Crash also happens/does not if a variable described above put here.
Database& _db;
// But not if it is here. Variable of any size is OK here.
};
class Derived : public Middle
{
public:
Derived() : Middle("Foo") { }
virtual ~Derived() { }
// Some virtual methods from Base overriden here.
};
简而言之,如果大小为 2 或更大的变量出现在 Database& _db
定义之前,就会发生崩溃。如果以后来,他们就不会了。
在这种情况下,如果无法访问调试器,我将如何尝试解决崩溃问题?
编辑:
class 用于加载 DLL 后的初始化方法 运行。不幸的是,我不能提供比这更多的细节。
int DllInitializer()
{
// Complex code.
DbPlugger::instance().addPlug(new Derived());
// Complex code.
}
您没有提供 mcve ,所以这是基于一些推测,但我假设您在某个时候隐式或显式地制作了一份副本。
所有三个导致崩溃的成员都可以轻松构造。由于您没有在构造函数中初始化它们,因此它们留下了不确定的值(假设非静态存储)。
复制此类对象时,会读取成员的值。读取(这些类型的)不确定值的行为是未定义的。当行为未定义时,程序可能会崩溃。
问题是存在两组不同的 Derived.h
/Derived.cpp
文件。其中之一已经过时,遗留在附近,永远被遗忘。
我一直在处理的集合包含在 C++ 项目本身中,但是包含实际头文件的源文件使用的是旧路径。
这导致 h 和 cpp 文件之间存在差异,由于项目中包含的头文件和项目中的一个 cpp 文件实际包含的头文件的内存签名不同,导致堆损坏。
通过 one-line #include
路径更改解决了很多调试和令人头疼的问题。
在 class 中定义变量会导致应用程序执行期间发生随机崩溃。
调试模式下不会出现崩溃,只会在发布版本中出现。
它也发生在不同的执行点。我在执行过程中时不时地输出日志,它们会时不时地不同。
问题中的class是继承链中的中间一个:
class Base
{
public:
virtual ~BaseClass() { }
// Quite a few virtual methods declared here.
};
class Middle : public Base
{
public:
virtual ~Middle() { }
protected:
Middle(const std::string& name)
: _name(name)
, _db(Context::DbInstance())
{
}
/**
* Commenting out any of the following crashes or does not.
*/
// CareTaker* _careTaker; // 4 bytes, crashes.
// void* dummy; // 4 bytes, crashes.
// int dummy; // 4 bytes, crashes.
// short dummy; // 2 bytes, crashes.
// class Dummy {}; // 1 bytes, does not crash.
// // 0 bytes, member removed, does not crash.
std::string _name;
// Crash also happens/does not if a variable described above put here.
Database& _db;
// But not if it is here. Variable of any size is OK here.
};
class Derived : public Middle
{
public:
Derived() : Middle("Foo") { }
virtual ~Derived() { }
// Some virtual methods from Base overriden here.
};
简而言之,如果大小为 2 或更大的变量出现在 Database& _db
定义之前,就会发生崩溃。如果以后来,他们就不会了。
在这种情况下,如果无法访问调试器,我将如何尝试解决崩溃问题?
编辑:
class 用于加载 DLL 后的初始化方法 运行。不幸的是,我不能提供比这更多的细节。
int DllInitializer()
{
// Complex code.
DbPlugger::instance().addPlug(new Derived());
// Complex code.
}
您没有提供 mcve ,所以这是基于一些推测,但我假设您在某个时候隐式或显式地制作了一份副本。
所有三个导致崩溃的成员都可以轻松构造。由于您没有在构造函数中初始化它们,因此它们留下了不确定的值(假设非静态存储)。
复制此类对象时,会读取成员的值。读取(这些类型的)不确定值的行为是未定义的。当行为未定义时,程序可能会崩溃。
问题是存在两组不同的 Derived.h
/Derived.cpp
文件。其中之一已经过时,遗留在附近,永远被遗忘。
我一直在处理的集合包含在 C++ 项目本身中,但是包含实际头文件的源文件使用的是旧路径。
这导致 h 和 cpp 文件之间存在差异,由于项目中包含的头文件和项目中的一个 cpp 文件实际包含的头文件的内存签名不同,导致堆损坏。
通过 one-line #include
路径更改解决了很多调试和令人头疼的问题。