C++ 二进制读/写中的SIGABRT

C++ 二进制读/写中的SIGABRT,c++,memory,serialization,io,C++,Memory,Serialization,Io,我编写了一个非常小的代码片段,并已得到以下错误: malloc:**对象0x100100080的错误:未分配要释放的指针 问题是,我不知道编译器在说什么指针。我通过地址将变量传递给读/写函数,但据我所知,我从未释放过它。我的代码中的错误在哪里?我和泄密者和僵尸一起运行,但什么也没有得到 以下是我的节目: #include <iostream> #include <fstream> #include <string> #include <vector>

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

malloc:**对象0x100100080的错误:未分配要释放的指针

问题是,我不知道编译器在说什么指针。我通过地址将变量传递给读/写函数,但据我所知,我从未释放过它。我的代码中的错误在哪里?我和泄密者和僵尸一起运行,但什么也没有得到

以下是我的节目:

#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;
}
#包括
#包括
#包括
#包括
#包括
使用名称空间std;
班级银行
{
私人:
字符串名称;
公众:
银行()
{ 
__name=“”;
}
银行(字符串名称)
{
__名称=名称;
}
字符串getName()常量{return\uu name;}
};
int main(int argc,char*const argv[]
{
银行(“美国银行”);
第二银行;

cout因为您的Bank类包含一个std::string,所以您不能像您所想的那样以二进制形式读/写它。std::string有内部指针。如果您以二进制形式写它,您将只写指针,而不是实际的字符串内容。同样,当您读取字符串时,您将读取指针。在本例中,y你最终使你的bank和bank2对象都有指向同一内存的字符串,所以当内存被释放时,它会被释放两次


您需要使用其他方法将银行数据写入文件。在这种情况下,使用银行名称的简单ASCII文件就可以了。

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


您需要使用其他方法将银行数据写入文件。在这种情况下,使用银行名称的简单ASCII文件就可以了。

您无法执行您正在执行的操作,原因很简单,
std::string
无法像这样复制。在内部,
string
对象分配内存和外部结构的简单副本没有达到你的期望


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

您无法执行您正在执行的操作,原因很简单,
std::string
不能像那样复制。在内部,
string
对象分配内存,而外部结构的简单副本不能执行您期望的操作

您需要正确序列化此结构

  • 请不要用下划线
  • 通过引用传递对象:
    银行(字符串和名称)
    ,请
  • 这是邪恶的:
    fout.write((char*)&bank,sizeof(bank));
  • 您可能需要编写
    您的
    银行
    类的团队操作符
  • 例如:

    friend std::ostream& operator<<(std::ostream &out, const Bank& b);
    friend std::istream& operator>>(std::istream &out, const Bank& b);
    
    friend std::ostream&operator(std::istream&out,const Bank&b);
    
  • 请不要用下划线
  • 通过引用传递对象:
    银行(字符串和名称)
    ,请
  • 这是邪恶的:
    fout.write((char*)&bank,sizeof(bank));
  • 您可能需要编写
    您的
    银行
    类的团队操作符
  • 例如:

    friend std::ostream& operator<<(std::ostream &out, const Bank& b);
    friend std::istream& operator>>(std::istream &out, const Bank& b);
    
    friend std::ostream&operator(std::istream&out,const Bank&b);
    
    无法读取包含带有fin.read()的std::string(或任何非纯Ol'数据)的对象--

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

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


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

    您不能用fin.read()读取包含std::string(或任何非纯Ol'数据)的对象--

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

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


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

    成员函数写入ostream和读取istream是专门为输入和输出二进制数据而设计的。如果您确实希望操作二进制数据,请使用以下命令:

    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;
    

    ostream的成员函数write和istream的成员函数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;
    

    不要使用标识符
    \u like\u this
    \u like\u this
    ,它们是保留给实现的。不要使用标识符
    \u like\u this
    \u like\u this
    ,它们是保留给实现的。出于好奇,下划线和按值传递有什么问题吗?为什么
    fout.write()
    evil?前两个不是evil:)只是好的做法。获取银行地址并强制转换为char是行不通的。如果要获取字符串字节,请编写一个GetBytes方法,返回u name::c_