【问题标题】:Why does WriteFile crash when writing to the standard output?为什么写入标准输出时 WriteFile 会崩溃?
【发布时间】:2012-01-01 23:53:29
【问题描述】:

这是一个使用 WinAPI 的 WriteFile(在 Microsoft Visual C++ 2008 Express 中编译)的“Hello world”程序:

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;
}

如果在控制台窗口中执行,它会愉快地迎接世界。但是,如果您尝试重定向其标准输出,如

hello.exe > output.txt

程序在 WriteFile 中崩溃(NULL 指针异常)。尽管如此,output.txt 仍然存在并包含完整的正确输出。

崩溃时的调用栈:

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++

消息:“srgprc2.exe 中 0x75ce85ea (KernelBase.dll) 处的未处理异常:0xC0000005:访问冲突写入位置 0x00000000。”

这里发生了什么?谢谢!

【问题讨论】:

  • 删除 CloseHandle() 调用。
  • ... 应该清楚,因为您使用的是 Get... 函数,而不是 Open... 函数。
  • CloseHandle 甚至没有被调用,崩溃发生在 WriteFile 并且程序终止。
  • 尝试复制句柄而不是获取它。另外,也许你得到了没有附加到任何东西的标准输出流,因为输出被重定向了?深入了解控制台进程的 I/O 重定向...
  • 既然 output.txt 生成正确,问题不在于悬空句柄...

标签: windows crash stdout writefile


【解决方案1】:

WriteFileis not optional 的第四个参数。您传递的是 NULL,这是不允许的。

【讨论】:

  • D'OH! “只有当 lpOverlapped 参数不为 NULL 时,此参数才能为 NULL。” msdn.microsoft.com/en-us/library/windows/desktop/…
  • 谢谢。原型中的“__out_opt”让我很困惑。
  • 我也遇到了与问题中提到的 OP 相同的问题。据我记得,我还为该参数传递了 NULL。所以...感谢您的出色回答。是的……+1 :)
【解决方案2】:

第四个参数(它告诉我们实际写入了多少字节)当您将 NULL 传递给该参数时,它会期望指向 DWORD 值的指针(又名无符号整数),它会尝试将 DWORD 写入空指针导致异常,不仅必须传递指向该参数的指针,而且您应该在写入后始终检查其值,因为尽管 WriteFile 写入的数据可能比您提供的少。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-11-19
    • 2016-07-08
    • 1970-01-01
    • 2019-05-31
    • 2011-04-17
    相关资源
    最近更新 更多