【问题标题】:Binary file loading leading to data loss二进制文件加载导致数据丢失
【发布时间】:2016-02-21 02:37:04
【问题描述】:

我正在尝试从已预先格式化的文件中读取数据,以便将其直接传递到顶点缓冲区。当读取超过一定大小的文件(高于 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 typedef 的 XMMATRIX 操作。
  • 您使用的是 float 而不是 FLOAT...这值得检查吗?

标签: c++ directx directx-11


【解决方案1】:

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

【讨论】:

  • 这似乎是问题所在。它现在正在完美加载。谢谢
【解决方案2】:

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

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

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

我会将你的变量声明为:

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();

另外 - 再次 - 您应该捕获所有文件流函数的返回值...它们可能会失败,您不会停下来检查原因...请参阅 SO 上 answer 中的代码格式

【讨论】:

  • 对不起,我明白你现在使用浮点数是什么意思了。我已经修改了变量以使用更适合的数据类型而不是浮点数,尽管这不是当前问题,因为我尝试加载的文件远小于浮点数和长整数的容量。
  • 对不起,为了代码 sn-p 的简洁,我删除了文件检查,因为我正在接收部分数据,我认为它们与问题无关。但是,我正在检查文件是否已加载,并检查第二次查找是否成功。不幸的是 f.clear() 似乎没有工作,我仍然只能加载部分数据。
  • @ZacHoward-Smith 很高兴 holtavolt 可以帮助你 :) 欢迎来到 Stack Overflow,祝你有美好的一天
  • 感谢您的帮助。
猜你喜欢
  • 1970-01-01
  • 2020-07-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-17
  • 1970-01-01
  • 2017-07-17
相关资源
最近更新 更多