【问题标题】:Weird output with WriteConsoleOutputAWriteConsoleOutputA 的奇怪输出
【发布时间】:2015-01-19 13:39:18
【问题描述】:

我正在尝试使用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);
}

【问题讨论】:

  • 与二维数组不同,二维向量的内存不能保证是连续的。

标签: c++ winapi memory console stdvector


【解决方案1】:

问题在于嵌套 std::vectors 的内存分配布局,以及它与 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);
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-12-03
    • 2015-02-18
    • 2011-06-14
    • 2013-06-04
    • 2021-02-08
    • 2014-12-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多