当我试图读取文件时,如何避免分割冲突

C++: how can avoid the segmentation violation when I try to read a file?

本文关键字:何避免 分割 冲突 文件 读取      更新时间:2023-10-16

我编写了这个函数,我希望它只是读取一个二进制文件并返回一个包含文件内容的向量。我遵循了一些关于如何使用"read"的教程,但我有一个分割违规。你能帮我理解一下吗?

const std::vector<uint32_t> read() {
    //obtain file size
    fseek( fBinaryFile, 0, SEEK_END );
    long lsize = ftell( fBinaryFile );
    rewind( fBinaryFile );
    uint32_t pDataBuffer[sizeof( uint32_t )*lsize];
    //read file
    fread( pDataBuffer, sizeof( uint32_t ), lsize, fBinaryFile );
    std::vector<uint32_t> cVector( pDataBuffer, pDataBuffer + sizeof( uint32_t )*lsize );
    closeFile();
    return cVector;
}

正如在问题的注释中已经说过的,您混淆了文件中的字节数和32位整数的数量,导致将垃圾读入向量的末尾。虽然这在技术上导致未定义的行为,但不太可能导致您所描述的崩溃。实际上,我不知道是什么导致了您所展示的代码的崩溃,但是考虑到代码的状态,我不得不假设您没有展示的代码包含类似的问题。

这是c++。为什么要处理C的文件访问器?使用流迭代器读取对象序列要容易得多。

为什么先读入缓冲区,然后将其复制到vector中,而不是立即读入vector ?

我仔细地重写了你的部分代码来解决这些问题。HTH。

// CAUTION! Brain-compiled code ahead
std::vector<uint32_t> read()
{
    std::fseek( fBinaryFile, 0, SEEK_END );
    const long numBytes = std::ftell( fBinaryFile );
    std::rewind( fBinaryFile );
    std::vector<uint32_t> cVector;
    cVector.resize( numBytes/sizeof(uint32_t) );
    if( !cVector.empty() ) {
        std::fread( &cVector[0], sizeof(uint32_t), lsize, fBinaryFile );
        std::closeFile();
    }
    return cVector;
}
您可能已经注意到,我从函数的返回类型中删除了 const 。这是因为它基本上是无用的。

首先,可变长度数组不是c++标准的一部分,即使一些编译器接受它作为扩展。

您处理的元素数量和大小存在混淆:lsize将是文件的字节长度,但您分配sizeof(uint32_t)*lsize元素的uint32_t数组。这比文件中可用的数据大sizeof(uint32_t)*sizeof(uint32_t) !请记住,这个大小必须小于SIZE_MAX。

我怀疑有一些内存溢出问题。因此,我建议您使用标准结构:

uint32_t *pDataBuffer = new uint32_t[sizeof( uint32_t )*lsize]; 

并考虑内存不足的可能性。

顺便说一下,你试着读lsize uint32_t。所以你读了比现在更多的书。

p。S:也许你可以考虑用ftell( fBinaryFile ) / sizeof(uint32_t)计算大小?还要确保大小不为0。

假设fBinaryFile是通过FILE *fBinaryFile = fopen(..., "rb");获得的,并且确保fBinaryFile不是NULL,那么以下操作应该可以工作:

FILE *fBinaryFile = fopen(..., "rb");
if (fBinaryFile == 0) {
    throw ...;  // do not proceed if file could not be opened
}
fseek( fBinaryFile, 0, SEEK_END );
long lsize = ftell( fBinaryFile );
rewind( fBinaryFile );

如果你的文件包含lsize/4 uint32_t values:

lsize /= sizeof( uint32_t );
uint32_t pDataBuffer[lsize];
//read file
fread( pDataBuffer, sizeof( uint32_t ), lsize, fBinaryFile );
std::vector<uint32_t> cVector( lsize );
for(int i=0; i<lsize; i++) cVector[i] = pDataBuffer[i]
close(fBinary);
return cVector;

如果你的文件包含lsize字节值,你想处理为uint32_t:

unsigned char pDataBuffer[lsize];
//read file
fread( pDataBuffer, sizeof( unsigned char ), lsize, fBinaryFile );
std::vector<uint32_t> cVector( lsize );
for(int i=0; i<lsize; i++) cVector[i] = pDataBuffer[i]
close(fBinary);
return cVector;