控制台无法输出,程序退出码-1073741819问题求助
问题描述
跟随One Lone Coder的控制台渲染教程编写代码后,在Visual Studio中按Ctrl+F5运行时控制台无任何输出,调试窗口显示程序以退出码-1073741819终止。代码如下:
#include <iostream> #include <Windows.h> #include <cmath> #include<chrono> using namespace std; int nscreenwidth = 120; int nscreenheight = 40; float fPlayerX = 8.0f; float fPlayerY = 8.0f; float fPlayerA = 0.0f; int nMapHeight = 16; int nMapWidth = 16; float fFOV = 3.1415 / 4.0; int main() { wchar_t* screen = new wchar_t[nscreenheight * nscreenwidth]; HANDLE hconsole = CreateConsoleScreenBuffer(GENERIC_READ | GENERIC_WRITE, 0, NULL, CONSOLE_TEXTMODE_BUFFER, NULL); SetConsoleActiveScreenBuffer(hconsole); DWORD dwBytesWritten = 0; wstring map; map += L"################"; map += L"#..............#"; map += L"#..............#"; map += L"#..............#"; map += L"#..............#"; map += L"#..............#"; map += L"#..............#"; map += L"#..............#"; map += L"#..............#"; map += L"#..............#"; map += L"#..............#"; map += L"#..............#"; map += L"#..............#"; map += L"#..............#"; map += L"#..............#"; map += L"#..............#"; map += L"################"; auto tp1 = chrono::system_clock::now(); auto tp2 = chrono::system_clock::now(); while (1) { tp2 = chrono::system_clock::now(); chrono::duration<float> elapsedtime = tp2 - tp1; tp1 = tp2; float fElapsedTime = elapsedtime.count(); if (GetAsyncKeyState((unsigned short)'A') & 0x8000) fPlayerA -= (0.1f * fElapsedTime); if (GetAsyncKeyState((unsigned short)'D') & 0x8000) fPlayerA += (0.1f * fElapsedTime); for (int x = 0; x < nscreenwidth; x++) { float fDistanceWall = 0; float fOffsetfov = (fPlayerA - fFOV / 2.0) + (((float)x / (float)nscreenwidth) * fFOV); float fUnitVecX = sinf(fOffsetfov); float fUnitVecy = cosf(fOffsetfov); bool bHitWall = false; while (!bHitWall && fDistanceWall < 16.0) { fDistanceWall += 0.1; int nTestX = (int)(fPlayerX + (fUnitVecX * fDistanceWall)); int nTestY = (int)(fPlayerY + (fUnitVecy * fDistanceWall)); if (nTestX < 0 || nTestX >= nMapWidth || nTestY >= nMapHeight) { bHitWall = true; fDistanceWall = 16.0f; } else if (map[nTestX * nMapWidth + nTestY] == '#') { bHitWall = true; } } int nCeiling = (float)(nscreenheight / 2.0) - nscreenheight / ((float)fDistanceWall); int nFloor = nscreenheight - nCeiling; for (int y = 0; y < nscreenheight; y++) { if (y > nCeiling) { screen[x * nscreenwidth + y] = ' '; } else if (y < nFloor) { if(fDistanceWall <= 16.0/4.0) screen[x * nscreenwidth + y] = '#'; else if (fDistanceWall < 16.0 / 2.0) screen[x * nscreenwidth + y] = '.'; else { screen[x * nscreenwidth + y] = ' '; } } } } screen[nscreenheight * nscreenwidth - 1] = '\\0'; WriteConsoleOutputCharacter(hconsole, screen, nscreenwidth * nscreenheight, { 0,0 }, &dwBytesWritten); } return 0; }
问题原因
- 数组越界访问(崩溃核心原因):地图索引计算错误,
map[nTestX * nMapWidth + nTestY]不符合地图行优先的存储逻辑。地图按行拼接,每行含nMapWidth个字符,正确索引应为行号×宽度+列号即nTestY * nMapWidth + nTestX,原代码颠倒X/Y顺序,导致访问超出map有效内存范围,触发内存错误直接崩溃。 - 屏幕缓冲区索引错误:
screen[x * nscreenwidth + y]不符合屏幕缓冲区行优先存储逻辑,正确索引应为y * nscreenwidth + x,原索引方式会导致越界或渲染混乱。 - 宽字符终止符错误:
screen[nscreenheight * nscreenwidth - 1] = '\\0';多了一个反斜杠,且未使用宽字符字面量L'\0',可能引发字符串处理异常。 - 未初始化屏幕缓冲区:动态分配的
screen数组未初始化,内存存在随机值,引发未定义行为。 - 旋转速度过慢:
0.1f * fElapsedTime的旋转系数太小,导致A/D键旋转效果几乎不可见,影响交互体验。
修复后的代码
#include <iostream> #include <Windows.h> #include <cmath> #include<chrono> #include <cstring> // 用于memset using namespace std; int nscreenwidth = 120; int nscreenheight = 40; float fPlayerX = 8.0f; float fPlayerY = 8.0f; float fPlayerA = 0.0f; int nMapHeight = 16; int nMapWidth = 16; float fFOV = 3.1415 / 4.0; int main() { wchar_t* screen = new wchar_t[nscreenheight * nscreenwidth]; // 初始化屏幕缓冲区为空格,避免未定义行为 memset(screen, ' ', nscreenheight * nscreenwidth * sizeof(wchar_t)); HANDLE hconsole = CreateConsoleScreenBuffer(GENERIC_READ | GENERIC_WRITE, 0, NULL, CONSOLE_TEXTMODE_BUFFER, NULL); SetConsoleActiveScreenBuffer(hconsole); DWORD dwBytesWritten = 0; wstring map; map += L"################"; map += L"#..............#"; map += L"#..............#"; map += L"#..............#"; map += L"#..............#"; map += L"#..............#"; map += L"#..............#"; map += L"#..............#"; map += L"#..............#"; map += L"#..............#"; map += L"#..............#"; map += L"#..............#"; map += L"#..............#"; map += L"#..............#"; map += L"#..............#"; map += L"#..............#"; map += L"################"; auto tp1 = chrono::system_clock::now(); auto tp2 = chrono::system_clock::now(); while (1) { tp2 = chrono::system_clock::now(); chrono::duration<float> elapsedtime = tp2 - tp1; tp1 = tp2; float fElapsedTime = elapsedtime.count(); // 提高旋转速度,让操作更直观 if (GetAsyncKeyState((unsigned short)'A') & 0x8000) fPlayerA -= 2.0f * fElapsedTime; if (GetAsyncKeyState((unsigned short)'D') & 0x8000) fPlayerA += 2.0f * fElapsedTime; for (int x = 0; x < nscreenwidth; x++) { float fDistanceWall = 0; float fOffsetfov = (fPlayerA - fFOV / 2.0) + (((float)x / (float)nscreenwidth) * fFOV); float fUnitVecX = sinf(fOffsetfov); float fUnitVecY = cosf(fOffsetfov); bool bHitWall = false; while (!bHitWall && fDistanceWall < 16.0) { fDistanceWall += 0.1; int nTestX = (int)(fPlayerX + fUnitVecX * fDistanceWall); int nTestY = (int)(fPlayerY + fUnitVecY * fDistanceWall); // 完善边界检查,包含nTestY < 0的情况 if (nTestX < 0 || nTestX >= nMapWidth || nTestY < 0 || nTestY >= nMapHeight) { bHitWall = true; fDistanceWall = 16.0f; } // 修正地图索引:行号(nTestY) × 宽度 + 列号(nTestX) else if (map[nTestY * nMapWidth + nTestX] == '#') { bHitWall = true; } } int nCeiling = static_cast<float>(nscreenheight / 2.0) - nscreenheight / static_cast<float>(fDistanceWall); int nFloor = nscreenheight - nCeiling; for (int y = 0; y < nscreenheight; y++) { // 修正屏幕缓冲区索引:行号(y) × 宽度 + 列号(x) if (y < nCeiling) { screen[y * nscreenwidth + x] = L' '; } else if (y > nFloor) { screen[y * nscreenwidth + x] = L' '; } else { if (fDistanceWall <= 16.0 / 4.0) screen[y * nscreenwidth + x] = L'#'; else if (fDistanceWall < 16.0 / 2.0) screen[y * nscreenwidth + x] = L'.'; else screen[y * nscreenwidth + x] = L' '; } } } // 设置正确的宽字符终止符 screen[nscreenheight * nscreenwidth - 1] = L'\0'; WriteConsoleOutputCharacter(hconsole, screen, nscreenwidth * nscreenheight, { 0,0 }, &dwBytesWritten); } // 释放动态分配的内存,避免内存泄漏 delete[] screen; return 0; }
修复要点
- 修正地图索引:将
nTestX * nMapWidth + nTestY改为nTestY * nMapWidth + nTestX,匹配地图行优先存储结构,解决数组越界问题。 - 修正屏幕缓冲区索引:将
x * nscreenwidth + y改为y * nscreenwidth + x,确保正确访问屏幕每个字符位置。 - 初始化屏幕缓冲区:使用
memset将screen数组初始化为空格,避免未定义行为。 - 修复宽字符终止符:将
'\\0'改为L'\0',符合宽字符字符串要求。 - 调整旋转速度:把旋转系数从
0.1f提升至2.0f,让A/D键旋转效果更明显。 - 添加内存释放:在程序结束前添加
delete[] screen;,释放动态分配的内存,避免内存泄漏。 - 完善边界检查:在地图碰撞检测中添加
nTestY < 0的判断,防止负索引越界。
内容的提问来源于stack exchange,提问作者prarthik krishnan
相关产品推荐
相关产品推荐

