将对象写入二进制文件时破坏堆

Corrupting the heap while writing an object to a binary file

我有这个 class 带有构造函数和析构函数

class Monster
{
    char* nume;
    double hp;
    float* dmgAbilitati;
    int nrAbilitati;

public:

    Monster(const char* nume, double hp, int nrAbilitati, float* dmgAbilitati)
    {
        if (nume == nullptr)
            throw new exception("Nume invalid!\n");
        else
        {
            this->nume = new char[strlen(nume) + 1];
            strcpy_s(this->nume, strlen(nume) + 1, nume);
        }
        if (hp <= 0)
            throw new exception("Hp invalid!\n");
        else
            this->hp = hp;
        if (nrAbilitati <= 0 && dmgAbilitati == nullptr)
            throw new exception("nrAbilitati invalid sau dmgAbilitati invalid!\n");
        else
        {
            this->nrAbilitati = nrAbilitati;
            this->dmgAbilitati = new float[nrAbilitati];
            for (int i = 0; i < nrAbilitati; i++)
                this->dmgAbilitati[i] = dmgAbilitati[i];
        }
    }

    ~Monster()
    {
        if (this->nume != nullptr)
            delete[] this->nume;
        if (this->dmgAbilitati != nullptr)
            delete[] this->dmgAbilitati;
    }
}

我正在尝试使用这两个函数写入和读取一个 Monster 对象to/from一个二进制文件

void scriereFisierBinar(ofstream& fisBinarOut)
    {
        int dim = strlen(nume) + 1;
        fisBinarOut.write((char*)&dim, sizeof(dim));
        fisBinarOut.write(this->nume, dim);

        fisBinarOut.write((char*)&this->hp, sizeof(this->hp));
        fisBinarOut.write((char*)&this->nrAbilitati, sizeof(this->nrAbilitati));

        for (int i = 0; i < this->nrAbilitati; i++)
            fisBinarOut.write((char*)(&this->dmgAbilitati[i]), sizeof(this->dmgAbilitati[i]));
    }

    void citireFisierBinar(ifstream& fisBinarIn)
    {
        int dim = 0;
        char aux[100];
        fisBinarIn.read((char*)&dim, sizeof(dim));

        fisBinarIn.read(aux, dim);
        if (nume != nullptr)
            delete[] nume;

        this->nume = new char[dim];
        strcpy_s(this->nume, dim, aux);

        fisBinarIn.read((char*)&this->hp, sizeof(this->hp));
        fisBinarIn.read((char*)&this->nrAbilitati, sizeof(this->nrAbilitati));

        for (int i = 0; i < this->nrAbilitati; i++)
            fisBinarIn.read((char*)(&this->dmgAbilitati[i]), sizeof(this->dmgAbilitati[i]));
        
    }

主要是我有这个:

float vvv[] = { 44,432,366,433,511 };
    Monster TEST000("Sper", 6969, 5, vvv);

    ofstream fisBinarOut("tt.bin", ios::out | ios::binary | ios::app);
    if (fisBinarOut.is_open())
    {
        TEST000.scriereFisierBinar(fisBinarOut);
        fisBinarOut.close();
    }
    else
        cout << "No!\n";

    float vvvv[] = { 1 };
    Monster mm("Nu", 3123, 1, vvvv);

    ifstream fisBinarIn("tt.bin", ios::in, ios::binary);
    if (fisBinarIn.is_open())
    {
        mm.citireFisierBinar(fisBinarIn);
        cout << mm;
        fisBinarIn.close();
    }
    else
        cout << "No\n";

我希望 'mm' 对象具有 'TEST000' 的属性,但只有名称和 Hp 发生变化,而且我收到一个堆错误:“检测到堆损坏。CRT 检测到应用程序写入了记忆中。”所以我猜测数组实现是错误的。 我附上了错误的图片和结果。此项目必须使用 char*。它还向析构函数抛出异常。

https://imgur.com/QWn80q5

问题出在citireFisierBinar:虽然对nume数组成员进行了重新分配,但dmgAbilitati没有重新分配(或至少检查是否有足够的内存)数组成员。
您的代码中还有一些其他问题,例如:

  • 抛出异常:ctor代码抛出一个指针;它应该抛出一个非指针值。
  • 它提供无异常保证:如果无法分配新内存,将抛出bad_alloc异常并且对象不会处于有效状态。比如numa的内存是在citireFisierBinar中释放的,那么你怎么看,析构函数会发生什么。或者在 ctor 中,如果抛出异常(由于无效的 arg),您的对象可能就像“半构造”并且内存泄漏。

这些是主要问题。