将对象写入二进制文件时破坏堆
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*
。它还向析构函数抛出异常。
问题出在citireFisierBinar
:虽然对nume
数组成员进行了重新分配,但dmgAbilitati
没有重新分配(或至少检查是否有足够的内存)数组成员。
您的代码中还有一些其他问题,例如:
- 抛出异常:ctor代码抛出一个指针;它应该抛出一个非指针值。
- 它提供无异常保证:如果无法分配新内存,将抛出
bad_alloc
异常并且对象不会处于有效状态。比如numa
的内存是在citireFisierBinar
中释放的,那么你怎么看,析构函数会发生什么。或者在 ctor 中,如果抛出异常(由于无效的 arg),您的对象可能就像“半构造”并且内存泄漏。
这些是主要问题。
我有这个 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*
。它还向析构函数抛出异常。
问题出在citireFisierBinar
:虽然对nume
数组成员进行了重新分配,但dmgAbilitati
没有重新分配(或至少检查是否有足够的内存)数组成员。
您的代码中还有一些其他问题,例如:
- 抛出异常:ctor代码抛出一个指针;它应该抛出一个非指针值。
- 它提供无异常保证:如果无法分配新内存,将抛出
bad_alloc
异常并且对象不会处于有效状态。比如numa
的内存是在citireFisierBinar
中释放的,那么你怎么看,析构函数会发生什么。或者在 ctor 中,如果抛出异常(由于无效的 arg),您的对象可能就像“半构造”并且内存泄漏。
这些是主要问题。