Why does WriteFile crash when writing to the standard output?
Asked Answered
C

2

14

Here's a "Hello world" program that uses WinAPI's WriteFile (compiled in Microsoft Visual C++ 2008 Express):

int _tmain(int argc, _TCHAR* argv[])
{
    wchar_t str[] = L"Hello world";

    HANDLE out = GetStdHandle(STD_OUTPUT_HANDLE);
    if(out && out!=INVALID_HANDLE_VALUE)
    {
        WriteFile(out, str, sizeof(str), NULL, NULL);
        CloseHandle(out);
    }   

    return 0;
}

If executed in a console window, it happily greets the world. If you try to redirect its standard output, however, as in

hello.exe > output.txt

the program crashes in WriteFile (NULL pointer exception). Nonetheless, output.txt exists and contains the correct output in its entirety.

The call stack on crash:

KernelBase.dll!_WriteFile@20()  + 0x75 bytes    
kernel32.dll!_WriteFileImplementation@20()  + 0x4e bytes    
srgprc2.exe!wmain(int argc=1, wchar_t * * argv=0x00483d88)  Line 15 + 0x16 bytes    C++

The message: "Unhandled exception at 0x75ce85ea (KernelBase.dll) in srgprc2.exe: 0xC0000005: Access violation writing location 0x00000000."

What's going on here? Thanks!

Christos answered 19/11, 2011 at 16:51 Comment(5)
Remove the CloseHandle() call.Crudden
... as should be clear, since you are using a Get... function, not an Open... function.Keely
The CloseHandle is not even called, the crash happens in WriteFile and the program terminates.Christos
Try duplicating the handle instead of getting it. Also, perhaps your'e getting the standard output stream which is not attached to anything, since the output is redirected? Look deeper into I/O redirection for console processes...Skit
Since output.txt is generated correctly, the problem is not a dangling handle...Christos
I
20

The fourth parameter to WriteFile is not optional. You are passing NULL, which is not allowed.

Isolecithal answered 19/11, 2011 at 17:16 Comment(3)
D'OH! "This parameter can be NULL only when the lpOverlapped parameter is not NULL." msdn.microsoft.com/en-us/library/windows/desktop/…Skit
Thank you. The "__out_opt" in the prototype confused me.Christos
I'm also having the same problem as OP mentioned in the question. And as far as I remember, I also passed NULL for that parameter. So...Thanks for your great answer. and yes... +1 :)Recant
H
0

4th parameter (which tells us how much bytes were actually written) is expecting pointer to DWORD value (a.k.a unsigned int) when you pass NULL to that parameter it attempts to write DWORD to null pointer which causes exception, not only it is mandatory to pass pointer to that argument but also you should always check its value after write because there is probability although slim that WriteFile will write less data than you provided.

Hod answered 5/8, 2017 at 2:7 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.