自定义二进制文件在 C++ 中触发故障位



tl;dr:自定义文件必须具有哪些必要的控制字符才能不触发[或触发]依赖于操作系统badbit, failbit, badbit, eofbit


我正在使用Cygwin和Notepad++,在x64笔记本电脑上使用Windows 7。

我有一个名为genesis.o的文件,我在十六进制编辑器中键入该文件,该文件与我正在从中读取/写入sandbox.cpp位于同一目录中。文件"genesis.o"包含:

genesis.o 
-----------------
58 - 4f - 58 - 4f 
58 - 58 - 58 - 58 
3f - 3f - 3f - 3f 
00 - 00 - 00 - 3f  
00 - 00 - 3f - 00
00 - 3f - 00 - 00
3f - 00 - 00 - 00 
00 - 00 - 00 - 58
00 - 00 - 58 - 00
00 - 58 - 00 - 00  
58 - 00 - 00 - 00 
48 - 45 - 4c - 4c  

到目前为止,我已经阅读和操作了自定义结构,而不考虑文件的有效性。我用stat来检查文件是否可以访问,这就足够了。

这个文件(带和不带扩展名".o"(通过了我所做的所有检查,除了它总是返回4(std::ios::failbit(的file.rdstate

错误不会显示在任何其他普通文件中,所以我猜测文件中/之后或文件中的某种控制字符序列实际上告诉std::fstream该文件是有效的。

由于没有其他文件(除了在十六进制编辑器中键入的文件(触发此行为,因此有没有办法构建一个自定义二进制文件以供 fstream 识别?某种控制字符、预设标志等?

我正在使用std::ios:in | std::ios:binary.我正在通过获取stat buffer.st_size-> 将其除以 4(因为我读取了 4 个字节整数(和:

uitn32_t temp = 0;
file.read( (char *)(&temp), sizeof(uint32_t) );  

值得一提的是,即使file.rdstate返回一个failbit,我也可以读取该二进制文件。

最小的可测试示例。只需使用上面的字符规范制作一个"genesis.o"文件。

#include <fstream>
#include <iostream>
#include <string>
#include <systypes.h>
#include <sysstat.h>
#include <vector>
struct handl{
std::string name = "genesis";
std::string ext  = "o";
std::vector<uint32_t> mem;
bool acces = false;
struct stat buffer;
handl():mem(0),name("genesis"),ext("o"){}
const char *f_name(){
std::string f_n = this->name;
f_n.append(".");
f_n.append(this->ext);
return f_n.c_str();
}
void recheck(){
this->acces = ( stat(this->f_name(), &this->buffer ) == 0 );
}
virtual bool header( std::fstream &file )
{return true;}
virtual bool footer( std::fstream &file )
{return true;}
void operator()(){ this->recheck(); }
void operator()( const char *name, const char *ext ){
this->name = std::string(name);
this->ext  = std::string(ext);
this->recheck();
}
void prefix( const char* pre ){
std::string pn(pre);
pn.append( this->name );
this->name = pn;
}
void suffix( const char *su ){
this->name.append(su);
this->recheck();
}
int read(){
this->recheck();
if( !this->acces ){return 0;}
std::fstream file;
file = std::fstream( this->f_name(), std::ios::in | std::ios::binary );
if( this->header(file) && this->footer(file) ){
int byte_size = this->buffer.st_size;
std::cout << file.rdstate() << std::endl;
std::cout << "gbt" << std::ios::goodbit << std::endl;
std::cout << "bbt" << std::ios::badbit  << std::endl;
std::cout << "ebt" << std::ios::eofbit  << std::endl;
std::cout << "fbt" << std::ios::failbit << std::endl;
file.close();
return 1;
}else{
file.close();
return 0;
}
}
};
int main(){
handl f;
std::cout << f.read() << std::endl;
return 0;
}
return f_n.c_str();

您的本地f_n对象被销毁,指向其内部存储器的指针悬空。使用它是一种未定义的行为。文件内容无关紧要。

我尝试了你的代码,这行:if( !this->acces ){return 0;}对我来说失败了。通过"失败",我的意思是这会导致read函数返回 0。

最新更新