随机定义一个指针会使程序崩溃

时间:2019-07-03 12:08:53

标签: c++ memory crash release dump

在类中定义变量会在应用程序执行期间导致随机崩溃。

该崩溃不会在调试模式下出现,它只会在发行版中发生。

它也发生在不同的执行点。我在执行过程中不时输出日志,它们有时会有所不同。

所讨论的类是继承链中的中间类:

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.
};

简而言之,如果在Database& _db定义之前添加了大小为2或更大的变量,则会发生崩溃。如果事后证明,则不会。

在这种情况下,我将如何尝试解决崩溃而又无法访问调试器?

编辑:

在加载DLL之后运行的初始化方法中使用该类。不幸的是,我无法提供更多细节。

int DllInitializer()
{
    // Complex code.

    DbPlugger::instance().addPlug(new Derived());

    // Complex code.
}

2 个答案:

答案 0 :(得分:1)

您尚未提供mcve,因此这是基于某种推测,但我认为您有时会隐式或显式地制作副本。

所有三个导致崩溃的成员都是微不足道的。由于您没有在构造函数中对其进行初始化,因此它们将保留不确定的值(假定为非静态存储)。

复制此类对象时,将读取成员的值。读取(这些类型的)不确定值的行为是不确定的。未定义行为时,程序可能会崩溃。

答案 1 :(得分:0)

问题在于,Derived.h / Derived.cpp文件有两组。其中一个已经过时,到处徘徊,永远被遗忘。

我正在处理的集合包含在C ++项目本身中,但是包含实际头文件的源文件却使用旧路径。

这导致h和cpp文件之间存在差异,由于项目中包含的头文件和项目中其中一个cpp文件实际包含的头文件的内存签名不同,导致堆损坏。

通过单行#include路径更改解决了很多调试和难题。