Consider this program:
#include <windows.h>
#include <stdio.h>
#pragma comment(linker, "/SUBSYSTEM:CONSOLE")
int main(void) {
if (!FreeConsole()) {
MessageBoxA(NULL, "FreeConsole failed", NULL, MB_ICONHAND);
return 1;
}
if (!AllocConsole()) {
MessageBoxA(NULL, "AllocConsole failed", NULL, MB_ICONHAND);
return 1;
}
FILE* newstdout;
if (freopen_s(&newstdout, "CONOUT$", "w", stdout)) {
MessageBoxA(NULL, "freopen_s failed", NULL, MB_ICONHAND);
return 1;
}
if (newstdout != stdout) {
MessageBoxA(NULL, "freopen_s did something wonky", NULL, MB_ICONHAND);
return 1;
}
puts("1");
MessageBoxA(NULL, "Look for 1 then press OK", NULL, 0);
return 0;
}
Steps to reproduce: create a new empty C/C++ project in Visual Studio 2019, go to Project Properties -> Configuration Properties -> Linker -> System and change SubSystem to Not Set, then add the above code to the project in a new file called Source.c
.
Most of the time I run it, it opens a new console with the number 1 in it, like it's supposed to, but sometimes it fails. If I used "Start Without Debugging" (Ctrl+F5) to run it, it fails about 1 run out of 30, with my "freopen_s failed" message. If I used "Start Debugging" (F5) to run it, it also fails about 1 run out of 10, with _NtClose
throwing an exception that says "An invalid handle was specified", with a stack trace pointing at my call to freopen_s
.
Why does this intermittent failure happen? Am I breaking one of the rules of the Windows API, either in the C code or in the project configuration?
Things I tried so far that didn't change the behavior:
- Removing the line with
#pragma
- Using
CON
in place ofCONOUT$
freopen_s
ingstdout
toNUL
before callingFreeConsole