带有指针和二进制文件的类
Classes with pointers and binary files
好吧,伙计们/女孩们,我已经问过这个问题,但我认为我没有解释得很好,我找不到解决方案,所以我会再次询问更多详细信息并解释更多我的问题的背景。
我有两个包含用户数据的类,我想将它们保存在二进制文件中。另一方面,我有一个模板类负责保存这些类。
我必须提到一个非常重要的事实:一开始,我为我要保存的任何类选择了编码辅助类。此辅助类负责写入/读取数据。原始类具有字符串成员,辅助类具有指向 char 的指针。但是最近,为了更加简单和灵活,我选择将包含字符串类优点的原始类与具有指针的辅助类结合起来,使类在保存时更舒适。因此,我没有两个类,而有一个处理数据输入/输出和数据写入/读取的类。
此更改如下所示:
class AuxNOTE;
//Original Class: Input/Output of Data
class NOTE{
private:
string _Category;
string _Description;
public:
NOTE() : _Category( "" ) , _Description( "" ) { }
NOTE( const NOTE & note ) : _Category( note._Category )
, _Description( note._Description ) { }
NOTE( string category , string description ) : _Category( category)
, _Description( description ) { }
NOTE( const AuxNOTE & aux ) : _Category( aux._Category )
, _Description( aux._Description ) { }
NOTE & operator=( const NOTE & note ){
_Category = note._Category;
_Description = note._Description;
return *this;
}
NOTE & operator=( const AuxNOTE & aux ){
_Category = string( aux._Category );
_Description = string( aux._Description );
return *this;
}
string GetCategory() const { return _Category; }
string GetDescription() const { return _Description; }
void SetCategory( string category ) { _Category = category; }
void SetDescription( string description ) { _Description = description; }
};
//Auxliary Class: Writing/Reading of Data to/from binary files
class AuxNOTE{
private:
char _Category[50];
char _Description[255];
public:
AuxNOTE(){ }
AuxNOTE( const NOTE & note ){
strcpy( _Category , note._Category );
strcpy( _Description , note._Description);
}
AuxNOTE & operator=( const NOTE & note ){
strcpy( _Category , note._Category );
strcpy( _Description , note._Description );
return *this;
}
};
我现在拥有的是这样的:
//Class NOTE: Input/Output of Data and Writing/Reading to/from binary files.
// .h file
class NOTE{
private:
char * _Category;
char * _Description;
public:
NOTE();
NOTE( const NOTE & note );
NOTE( string category , string description );
NOTE & operator=( const NOTE & note )
string GetCategory() const;
string GetDescription() const;
void SetCategory( string category );
void SetDescription( string description );
};
// .cpp file
#include "NOTE.h"
NOTE :: NOTE() : _Category( nullptr ) ,_Description( nullptr )
{
}
NOTE :: NOTE( string description , string category )
: _Category ( new char[ category.size() + 1 ] )
, _Categoria( new char[ description.size() + 1 ] )
{
strcpy( _Categoria , category.c_str() );
strcpy( _Descripcion , description.c_str() );
}
NOTE :: NOTE (const NOTE & copy )
: _Category( nullptr )
, _Description nullptr )
{
if( copy._Description != nullptr ){
_Description = new char[ strlen( copy._Description ) + 1 ];
strcpy( _Description , copy._Description );
}
if( copy._Category != nullptr ){
_Category = new char[ strlen( copy._Category ) + 1 ];
strcpy( _Category , copy._Category );
}
}
NOTE :: ~NOTE() {
if( _Description != nullptr ) delete [] _Description;
if( _Category != nullptr ) delete [] _Category;
}
//Get Methods
string NOTE :: GetDescription() const { return string(_Description); }
string NOTE :: GetCategory() const { return string(_Category); }
//Set Methods
void NOTE :: SetDescription( string description ){
if( _Description != nullptr ) delete [] _Description;
_Description = new char[ description.size() + 1 ];
strcpy( _Description , description.c_str() );
}
void NOTE :: SetCategory( string category ){
if( m_Category != nullptr ) delete [] _Category;
_Category = new char[ category.size() + 1 ];
strcpy( _Category , category.c_str() );
}
//Operators
NOTE & NOTE :: operator=( const NOTE & note ){
if( note._Description != nullptr ) SetDescription( note.GetDescription() );
if( note._Category != nullptr ) SetCategory( note.GetCategory() );
return *this;
}
请注意,如果 NOTE 类适用于字符串成员,则公共接口看起来很像,但事实并非如此,因为它适用于指向字符的指针。因此,可以毫无问题地保存 NOTE 类。但是,该类根本不负责写作/阅读,但我创建了另一个类,只要这些类具有可以保存的成员,就可以保存任何类。
负责此操作的类是一个模板类,如下所示:
template< class T >
class SAVER{
private:
vector< T > _Vector;
string _File;
public:
SAVER( string file );
~SAVER();
};
template< class T >
SAVER< T > :: SAVER( string file ) : _File( file ){
assert( _File != "" );
ifstream file( _File , ios::binary );
if( file.is_open() ){
T obj;
while( file.read( reinterpret_cast<char*>(&obj) , sizeof(obj) ) )
_Vector.push_back( obj );
}
}
template< class T >
Saver< T > :: ~Saver() {
if( _Vector.empty() )
return;
ofstream file( _File , ios::binary | ios::trunc );
assert( file.is_open() );
auto itr = _Vector.begin();
auto end = _Vector.end();
while( itr != end ){
if ( !file.write( reinterpret_cast<char*>( &itr ) , sizeof(itr) ) )
break;
itr++;
}
}
SAVER的构造函数处理读取并将数据(例如NOTE对象)放入其向量中。销毁器处理将所有矢量的对象写入相应的二进制文件。
我必须清楚我的错误不是编译错误,而是运行时错误。
现在,这就是我遇到的问题:
当我执行整个程序时,它必须读取二进制文件,但它会中断。我用调试器打开它,我看到程序在这一行中以"分段错误错误"结束,这来自 SAVER 构造函数:
NOTE :: ~NOTE() {
if( _Description != nullptr ) delete [] _Description; //It breaks at this line
if( _Category != nullptr ) delete [] _Category;
}
在调试器中,我可以看到 _Description 的值,旁边出现一个内存错误,上面写着:错误:无法访问地址(值为 _Description)的内存。
为什么会这样?你看到任何错误吗?如果您需要更多信息或不了解某些内容,请告诉我。
首先,在互联网上搜索"c++ 序列化库"。 您正在执行的操作称为序列化。
指针和任何包含指针的类都不能逐字写入文件。 指针是内存中的位置。 大多数操作系统不能保证程序下次执行时具有确切的内存位置。 您的程序可能会在不同的内存区域中运行,这会更改数据的存储位置。
有一些技术可以解决这个问题,例如先写入数量,然后写入数据,或者先写入数据,然后写入某种哨兵(例如 C 样式字符串中的"\0")。
请考虑不要以二进制文件的形式编写,而是使用格式化的文本表示形式。 许多平台将读入数字并将其转换为本机表示。 以二进制模式写入文件的本机表示形式,在另一个平台上许多并不相同(查找"Endianess")。 此外,大多数文本编辑器和文字处理器都可以轻松读取文本文件。 读取和解释二进制文件更加困难。
除非应用程序的瓶颈是 I/O 限制的,并且 I/O 计时至关重要,否则请考虑使用数据的文本表示形式。 它更易于阅读(尤其是在调试程序时)且易于移植。
在调试器中,我可以看到 _Description 的值,旁边出现一个内存错误,上面写着:错误:无法访问地址(值为 _Description)的内存。
当然,您无法从二进制文件中反序列化指针。您需要将其大小信息和内容存储在文件中。
- 正在读取二进制文件(is_open)
- 在C++中将类(带有Vector成员)保存为二进制文件
- 如何从二进制文件中读取字符串
- 保存/加载大量短数组到二进制文件
- 从二进制文件中读取整数数组
- Android 在编译二进制文件时重建静态库
- 在 C++ 中将双精度变量写入二进制文件
- clang 的 libFuzzer 可以在同一二进制文件中测试超过 1 个 API 吗?
- C++:实际上不是从二进制文件中读取
- 如何从二进制文件中的给定符号中获取调用程序图
- 将内部带有矢量的结构保存/读取到二进制文件中
- 编译多个C++文件.调用二进制文件以运行代码
- 如何使用位字段将数据从二进制文件复制到结构中?
- 使用此指针在 c++ 中将对象写入二进制文件
- C++:使用std::ifstream读取二进制文件后删除缓冲区/指针时发生访问冲突
- 将对象(指针)在地图中输出到二进制文件
- 用于在二进制文件上写入函数的 cpp 指针
- 带有指针和二进制文件的类
- 如何写入和读取指向二进制文件的指针
- 正在将void指针写入二进制文件