WriteConsoleOutputA 的奇怪输出
Weird output with WriteConsoleOutputA
我正在尝试使用 WriteConsoleOutputA()
和 std::vector<CHAR_INFO>
在 Win32 控制台中打印彩色图案;一切似乎都很好。但是,当我尝试使用二维向量 std::vector<std::vector<CHAR_INFO>>
时,WrtieConsoleOutputA()
会在输出中获取一些内存垃圾。我不知道我的代码中的错误在哪里。
这是我的代码:
#include <ctime>
#include <Windows.h>
#include <vector>
int main()
{
srand((unsigned)time(NULL));
const int width = 80, height = 25;
COORD charBufferSize{ width, height };
COORD characterPosition{ 0, 0 };
SMALL_RECT writeArea{ 0, 0, width - 1, height - 1 };
std::vector<std::vector<CHAR_INFO>> backBuffer(height, std::vector<CHAR_INFO>(width));
for (auto& i : backBuffer)
{
for (auto& j : i)
{
j.Char.AsciiChar = (unsigned char)219;
j.Attributes = rand() % 256;
}
}
WriteConsoleOutputA(GetStdHandle(STD_OUTPUT_HANDLE), backBuffer[0].data(), charBufferSize, characterPosition, &writeArea);
}
问题是 nested std::vector
的内存分配布局,它与 Win32 API WriteConsoleOutput()
期望的不匹配。
std::vector
连续分配内存。但是,如果你有一个 std::vector
嵌套在 一个外部 std::vector
,那么 整个 分配的内存是 不再连续!
如果你想要一个完整的连续内存块,你应该分配一个单个std::vector
,总大小为width x height
,并将其用作内存WriteConsoleOutput()
.
的缓冲区
我按照这条路径稍微修改了你的代码,现在它似乎可以工作了:
#include <ctime>
#include <Windows.h>
#include <vector>
int main()
{
srand((unsigned)time(NULL));
const int width = 80;
const int height = 25;
COORD charBufferSize{ width, height };
COORD characterPosition{ 0, 0 };
SMALL_RECT writeArea{ 0, 0, width - 1, height - 1 };
//
// NOTE:
//
// Wrong memory layout: vector<vector<...>> is *not* contiguous as a whole
//
// std::vector<std::vector<CHAR_INFO>> backBuffer(height,
// std::vector<CHAR_INFO>(width));
//
//
// Correct memory layout: allocate a single *contiguous* block
// of memory, to store a 2D array of width x height
//
std::vector<CHAR_INFO> backBuffer(width * height);
//
// Iterate through the backBuffer items
// as if it were a 2D array of size width x height
//
for (size_t row = 0; row < height; ++row)
{
for (size_t col = 0; col < width; ++col)
{
CHAR_INFO& curr = backBuffer[row*width + col];
// Your previous code
curr.Char.AsciiChar = static_cast<unsigned char>(219);
curr.Attributes = rand() % 256;
}
}
WriteConsoleOutputA(GetStdHandle(STD_OUTPUT_HANDLE),
backBuffer.data(),
charBufferSize,
characterPosition,
&writeArea);
}
我正在尝试使用 WriteConsoleOutputA()
和 std::vector<CHAR_INFO>
在 Win32 控制台中打印彩色图案;一切似乎都很好。但是,当我尝试使用二维向量 std::vector<std::vector<CHAR_INFO>>
时,WrtieConsoleOutputA()
会在输出中获取一些内存垃圾。我不知道我的代码中的错误在哪里。
这是我的代码:
#include <ctime>
#include <Windows.h>
#include <vector>
int main()
{
srand((unsigned)time(NULL));
const int width = 80, height = 25;
COORD charBufferSize{ width, height };
COORD characterPosition{ 0, 0 };
SMALL_RECT writeArea{ 0, 0, width - 1, height - 1 };
std::vector<std::vector<CHAR_INFO>> backBuffer(height, std::vector<CHAR_INFO>(width));
for (auto& i : backBuffer)
{
for (auto& j : i)
{
j.Char.AsciiChar = (unsigned char)219;
j.Attributes = rand() % 256;
}
}
WriteConsoleOutputA(GetStdHandle(STD_OUTPUT_HANDLE), backBuffer[0].data(), charBufferSize, characterPosition, &writeArea);
}
问题是 nested std::vector
的内存分配布局,它与 Win32 API WriteConsoleOutput()
期望的不匹配。
std::vector
连续分配内存。但是,如果你有一个 std::vector
嵌套在 一个外部 std::vector
,那么 整个 分配的内存是 不再连续!
如果你想要一个完整的连续内存块,你应该分配一个单个std::vector
,总大小为width x height
,并将其用作内存WriteConsoleOutput()
.
我按照这条路径稍微修改了你的代码,现在它似乎可以工作了:
#include <ctime>
#include <Windows.h>
#include <vector>
int main()
{
srand((unsigned)time(NULL));
const int width = 80;
const int height = 25;
COORD charBufferSize{ width, height };
COORD characterPosition{ 0, 0 };
SMALL_RECT writeArea{ 0, 0, width - 1, height - 1 };
//
// NOTE:
//
// Wrong memory layout: vector<vector<...>> is *not* contiguous as a whole
//
// std::vector<std::vector<CHAR_INFO>> backBuffer(height,
// std::vector<CHAR_INFO>(width));
//
//
// Correct memory layout: allocate a single *contiguous* block
// of memory, to store a 2D array of width x height
//
std::vector<CHAR_INFO> backBuffer(width * height);
//
// Iterate through the backBuffer items
// as if it were a 2D array of size width x height
//
for (size_t row = 0; row < height; ++row)
{
for (size_t col = 0; col < width; ++col)
{
CHAR_INFO& curr = backBuffer[row*width + col];
// Your previous code
curr.Char.AsciiChar = static_cast<unsigned char>(219);
curr.Attributes = rand() % 256;
}
}
WriteConsoleOutputA(GetStdHandle(STD_OUTPUT_HANDLE),
backBuffer.data(),
charBufferSize,
characterPosition,
&writeArea);
}