ifstream 在 x64 位平台上崩溃

ifstream is crashing on x64 bit platform

我正在尝试使用 ifstream 打开一个 txt 文件并使用 ifstream 从该文件中读取数据,而该代码在 x86 位平台上工作得很好,它会导致奇怪的应用程序崩溃在 x64 位平台上使用它。

ifstream font;

font.open(filename);
if ( font.fail() )
{
    return false;
}

// Used to read 95 ASCII characters in the text file
for ( int i = 0; i < 95; i++ )
{
        font.get(temp);
        while (temp != ' ')
        {
            font.get(temp);
        }

        font.get(temp);
        while (temp != ' ')
        {
            font.get(temp);
        }

        font >> m_Font[i].left;
        font >> m_Font[i].right;

        font >> m_Font[i].size;
}

删除 font.fail() 检查导致程序卡在 font.get(temp); 这意味着 font.fail() 导致程序崩溃,如果有人知道这个问题的解决方案或者可以指出在此上下文中读取文本文件的另一种方法,请告诉我。

可以在下面找到可重现的示例,确保将构建配置设置为 x64 并将子系统设置为 Windows`

#include <Windows.h>
#include <iostream>
#include <fstream>

using namespace std;

struct TestStruct
{
    int test;
}; TestStruct* testStruct;

bool Test(char* filename)
{
    testStruct = new TestStruct[8];
    if (!testStruct)
    {
        return false;
    }

    ifstream font;
    font.open(filename);
    if (font.fail())
    {
        return false;
    }

    char temp;

    for ( int i = 0; i < 8; i++)
    {
        font.get(temp);
        while (temp != ' ')
        {
            font.get(temp);
        }

        font.get(temp);
        while (temp != ' ')
        {
            font.get(temp);
        }

        font >> testStruct[i].test;
    }

    font.close();

    return true;
}

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR pScmdline, int iCmdshow)
{
    AllocConsole();
    freopen("CONOUT$", "w", stdout);
    
    while ( Test((char*)"test.txt") )
    {
    }

    return 0;
}

P.S 我在从构建文件夹中单独执行二进制文件时未能重现此问题,但是在使用本地 windows 附加调试器启动它时仍然会出现此问题。

您有一个无限循环,它使用相同的参数调用相同的函数。此函数执行完全相同的过程,但具有创建 TestStruct.

数组的副作用

当一切“正常”时,函数 returns 为真,并再次被调用。一个问题是您永远不会删除在函数内部动态创建的数组。这意味着你迟早会 运行 内存不足,并且这个无限循环将被打破。但是它不会按照您计划的方式被破坏:operator new(您正在使用的那个)会抛出异常(std::bad_alloc)而不是返回 nullptr.

这就是我从您的代码中看到的。编译器可能会看到相同的结果,它可以以许多奇怪的方式优化代码以实现相同的行为。尝试纠正导致 UB 和内存泄漏的问题,也许编译器会改变主意。

所以正如一些人指出的那样,从一种字符串类型转换为另一种类型,在这种情况下,从 const char* 转换为 char* 会导致未定义的行为,起初我在可重现的示例中修复了它但是无法在我的主项目中修复它,但是在将所有字符串类型更改为原始函数使用的字符串类型后,它解决了问题,即:

D3DX11CreateShaderResourceViewFromFile 正在使用 LPCTSTR 并在我尝试从 WCHAR*

转换 LPCTSTR 时导致崩溃