二进制文件加载导致数据丢失

Binary file loading leading to data loss

我正在尝试从预先格式化的文件中读取数据,以便将其直接传递到顶点缓冲区中。当读取超过一定大小(大于 1152 字节但小于 92,160 字节)的文件时,它会失败。它将一些值从文件写入分配的内存,在不设置其余值之前,留下值 -431602080,这似乎是代表干净内存的 CRT 值(SO Source)。它的值的数量成功写入似乎随文件大小而变化。

我调查过我是否超出了分配限制,但似乎并非如此。我已经检查以确保分配不会因其他原因而失败。我已经将数据读入一个之前填充了值的向量,以查看它是否手动写入值-431602080,但是之前的值仍然表明它只是无法写入内存。

void Mesh::LoadMeshFromFile(DXManager* dxPtr, LPCSTR fileName, int ID)
{
    std::fstream f(fileName, std::ios_base::in);
    short vertexStride = sizeof(Vertex);                            //Gets the stride per vertex
    long fileLength = f.seekg(0, std::ios::end).tellg();            //Gets the byte count
    float vertexCount = (float)fileLength / (float)vertexStride;    //Calculates the vertex count

    if (vertexCount == (int)vertexCount)    //Ensures there are no incomplete vertices
    {
        if (vertexCount > 134217727 || vertexCount * vertexStride > 2147483647)
        {
            //Alloc will definitely fail.
            //Throw an error
        }
        else
        {
            char* vertices = new __nothrow char[(int)fileLength];
            if (vertices == NULL)
            {
                //Allocation failed
                //Throw an error
            }
            else
            {
                //Read all vertices directly into the array and build the buffer
                f.seekg(0, std::ios::beg);
                f.read(vertices, fileLength);
                BuildBuffer(dxPtr, (Vertex*)vertices, vertexCount);     
            }
        }
    }
    else
    {
        //1 or more incomplete vertices.
    }
}

下面是一个示例输出。某些文件不会出现此问题,并且似乎与文件大小有关。数据丢失发生的位置不是固定的,而且似乎还因文件大小而异。

如您所见,数据在第 4 个条目之前有效,部分通过该行。 希望有人能够阐明正在发生的事情。

您可以用单精度成功表示的最大连续整数(从零开始计数)float 是 2^24,或 16,777,216。您的文件长度很容易超过 float 可以准确表示的大小。

对整数值使用 longint,并在需要时类型转换为 float。反之则不然。

如果您尝试读取比文件中实际存在的字节更多的字节,由于 float-to-long 中的转换错误 f.read(vertices, fileLength);,您将无法正确读取数据- 并获得可能的腐败。

我会将您的变量声明为:

long vertexStride = sizeof(Vertex);                    //Gets the stride per vertex
long fileLength = f.seekg(0, std::ios::end).tellg();   //Gets the byte count
float vertexCount = fileLength / vertexStride;          //Calculates the vertex count

此外,如果 seekg 未清除 EOF 标记,请清除文件流。 在查找开始之前使用 f.clear();

另外 - 再次 - 你应该从你的所有文件流函数中捕获 return 值......它们可能会失败,你不会停下来检查原因......请参阅此[=中的代码格式21=] 在 SO

由于这是一个二进制文件,您需要指定 ios::binary(fstream 默认为文本)