二进制读/写中的SIGABRT

SIGABRT in binary read/write

本文关键字:SIGABRT 二进制      更新时间:2023-10-16

我写了一个非常小的代码片段,已经得到了以下错误:

malloc: *** error for object 0x100100080: pointer being freed was not allocated

问题是,我不知道编译器在说什么指针。我通过地址将一个变量传递给读/写函数,但据我所知,我从未释放过它。我的代码中的错误在哪里?我和Leaks和Zombies合作过,但一无所获。

这是我的程序:

#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <algorithm>
using namespace std;
class Bank
{
 private:
    string __name;
 public:
   Bank() 
   { 
      __name = ""; 
   }
   Bank(string name) 
   {
      __name = name; 
   }
    string getName() const { return __name; }
};

 int main (int argc, char * const argv[]) 
{
    Bank bank("Bank of America");
    Bank bank2;
    cout << "Bank1: " << bank.getName() << endl; 
    string filename = bank.getName() + ".bank";
    ofstream fout(filename.c_str(), ios::binary);
    if (fout.good())
      fout.write((char *)&bank, sizeof(bank));
    fout.close();
    ifstream fin(filename.c_str(), ios::binary);
    if (fin.good())
      fin.read((char *)&bank2, sizeof(bank2));
    fin.close();
    cout << "Bank2: " << bank2.getName() << endl;
    return 0;
}

使用fin.read()--无法读取包含std::字符串(或任何非纯Ol数据的对象)的对象

对象是以字节流的形式读取和写入的,但std:string包含一个指向存储在其他地方的内存的指针,该指针不是用fout.write()写入的,也不是用fin.read()正确初始化的

这是因为它没有用fin.read()正确初始化,所以您得到了堆错误;当对象超出范围时,会调用初始化不正确的std::string的析构函数,并试图释放它不拥有的内存。

您可能想要为对象编写一个自定义的i/o方法,并逐个保存或加载它。要获得执行此操作的快捷方式,请使用Boost序列化库。

因为您的Bank类包含std::字符串,所以您不能像您所想的那样将其读/写为二进制。std::字符串具有内部指针。如果你把它写成二进制,你只会写指针,而不是实际的字符串内容。同样,当你读取字符串时,你将读取一个指针。在这种情况下,您最终会使bank和bank2对象都有指向同一内存的字符串,因此当该内存被释放时,它会被释放两次。

你需要用其他方式将你的银行数据写入文件。在这种情况下,一个带有银行名称的简单ASCII文件就可以了。

你不能做你正在做的事情,因为std::string不能像那样复制。在内部,string对象分配内存,而外部结构的简单副本并不能达到预期效果。

您需要正确地序列化此结构。

  1. 请不要使用下划线
  2. 参照传递对象:Bank(string& name)
  3. 这是邪恶的:fout.write((char *)&bank, sizeof(bank));
  4. 您可能想要在Bank类的ostream操作符中编写<<>>

例如:

friend std::ostream& operator<<(std::ostream &out, const Bank& b);
friend std::istream& operator>>(std::istream &out, const Bank& b);

ostream的成员函数write和istream的Members函数read专门设计用于输入和输出二进制数据。如果您确实想操作二进制数据,请使用以下方法:

ifstream fin(filename.c_str(), ios::in|ios::binary|ios::ate);
size = fin.tellg();
memblock = new char [size];
fin.seekg(0, ios::beg);
if (fin.good()){
   fin.read(memblock, size);
   fin.close();
}
delete[] memblock;