I've disabled line input with the following code:
DWORD dwConsoleMode;
GetConsoleMode(hStdIn, &dwConsoleMode);
dwConsoleMode ^= ENABLE_LINE_INPUT;
SetConsoleMode(hStdIn, dwConsoleMode);
Then I am calling ReadConsole in a loop...in a loop:
wchar_t cBuf;
while (1) {
/* Display Options */
do {
ReadConsole(hStdIn, &cBuf, 1, &dwNumRead, NULL);
} while (!iswdigit(cBuf));
putwchar(cBuf);
if (cBuf == L'0') break;
}
If I run the program and press 0 right away, it exists cleanly.
But if I press a bunch of keys, then press 0, when the program exists it crashes with:
Run-Time Check Failure #2 - Stack around the variable 'cBuf' was corrupted.
Why is this causing the stack to become corrupt? The code is simple, so I can't figure out what is wrong.
Little program that I can reproduce the problem with:
#include <windows.h>
#include <stdio.h>
int wmain(int argc, wchar_t *argv[])
{
DWORD dwNumRead;
wchar_t cBuf;
HANDLE hStdIn = GetStdHandle(STD_INPUT_HANDLE);
DWORD dwConsoleMode;
GetConsoleMode(hStdIn, &dwConsoleMode);
dwConsoleMode ^= ENABLE_LINE_INPUT;
SetConsoleMode(hStdIn, dwConsoleMode);
while (true)
{
wprintf(L"\nEnter option: ");
do {
ReadConsoleW(hStdIn, &cBuf, 1, &dwNumRead, NULL);
} while (!iswdigit(cBuf));
putwchar(cBuf);
if (cBuf == L'0') break;
}
return 0;
}
You have to kind of mash your keyboard after you run it, then press 0, and it crashes with the stack corruption.
I also can't reproduce the problem every time, it takes a few tries.
I was running it under Visual Studio 2010, after creating a new empty console project and adding a file with that code.
As far as I can tell, this is a bug in Windows. Here is a slightly simpler program that demonstrates the problem:
#include <windows.h>
#include <crtdbg.h>
int wmain(int argc, wchar_t *argv[])
{
DWORD dwNumRead;
wchar_t cBuf[2];
cBuf[0] = cBuf[1] = 65535;
HANDLE hStdIn = GetStdHandle(STD_INPUT_HANDLE);
SetConsoleMode(hStdIn, 0);
while (true)
{
_ASSERT(ReadConsoleW(hStdIn, &cBuf[0], 1, &dwNumRead, NULL));
_ASSERT(dwNumRead == 1);
_ASSERT(cBuf[1] == 65535);
Sleep(5000);
}
}
The sleep makes it a bit easier to trigger the issue, which occurs whenever more than one character is waiting at the time you call ReadConsoleW.
Looking at the content of cBuf[1]
at the time the relevant assertion fails, it appears that ReadConsoleW is writing one extra byte at the end of the buffer.
The workaround is straightforward: make sure your buffer has at least one extra byte. In your case, use the first character of a two-character array.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With