【问题标题】:Why does writing to STD_OUTPUT_HANDLE crash under Sublime Text? [duplicate]为什么在 Sublime Text 下写入 STD_OUTPUT_HANDLE 会崩溃? [复制]
【发布时间】:2016-11-21 11:40:18
【问题描述】:

我有一个应用程序,它碰巧在从 GetStdHandle 获取的句柄上使用 winapi 的 WriteFile 登录到控制台。最小测试用例:

#include <Windows.h>

int main(int argc, char** argv) {
  HANDLE console = GetStdHandle(STD_OUTPUT_HANDLE);
  if(GetFileType(console) == FILE_TYPE_UNKNOWN)
    return;
  WriteFile(console, "abc", 3, 0, 0);
}

在 VS2013 中使用默认选项构建。当在标准 Windows 控制台上调用以及从 python2/python3/Sublime 的控制台调用时使用例如subprocess.Popen('/path/to/my.exe').

现在我想在 SublimeText 3 中将这个程序作为构建系统运行。这是构建定义:

{
  "cmd": [ "/path/to/my.exe" ]
}

根据documentation,这应该相当于使用 subprocess.Popen。但是,当我调用这个“构建系统”时,Sublime 的输出窗格会显示 abc,然后对 WriteFile 的调用会崩溃

0xC0000005: Access violation writing location 0x00000000.

这里发生了什么?这是我的代码、Sublime 或 WriteFile 中的问题吗?有什么可以做的吗? (我尝试使用 shell_cmd 而不是 cmd 但这没有区别)

【问题讨论】:

  • 仅在 XP 上崩溃?你在哪个 Windows 版本上检查这个?
  • 仅在 Windows 7 上测试
  • 对不起,我看起来很糟糕 - 如果lpNumberOfBytesWritten==0 仅从 win 8.1 开始,那么真的在 win7 上也一定会崩溃,这已更改并且还没有崩溃

标签: python winapi console subprocess sublimetext3


【解决方案1】:

您将错误的参数传递给WriteFile

lpNumberOfBytesWritten [输出,可选]
只有当 lpOverlapped 参数不为 NULL 时,该参数才可以为 NULL。

对于WriteFile 的同步调用,您必须将有效指针传递给DWORD,返回写入的字节数:

#include <Windows.h>

int main(int argc, char** argv) {
  HANDLE console = GetStdHandle(STD_OUTPUT_HANDLE);
  if(GetFileType(console) == FILE_TYPE_UNKNOWN)
    return;
  DWORD dwBytesWritten{};
  WriteFile(console, "abc", 3, &dwBytesWritten, 0);
}

【讨论】:

  • bonks head on keyboard 所以我们很幸运这个应用程序已经在数十台不同的机器上运行了数千小时,将数千行打印到控制台没有任何问题?知道为什么特别是在 Sublime 下会出现这种情况吗?
  • @stijn:我对此进行了一些思考,但无法给出解释,为什么这似乎在某些条件下可靠地工作,但在其他条件下却不行。我唯一能想象的是,I/O 流重定向在其中起作用,当你幸运时,重定向的流不会报告写入的字节,WriteFile 永远不会尝试写入*lpNumberOfBytesWritten。不过,这是猜测。
  • @stijn - 真正的 WriteFile 检查 lpNumberOfBytesWritten != 0 并仅在这种情况下使用此指针(独立于流重定向)。但是根据文档确实需要使用有效而不是零lpNumberOfBytesWritten - 了解错误的确切位置 - 最佳选择 - 调试代码
  • 错误绝对不是因为 lpNumberOfBytesWritten == 0
  • 在 Windows 7 和更早版本上,控制台句柄是伪句柄而不是真实句柄。我认为这意味着写入操作会通过完全不同的代码路径,因此会出现一些行为差异。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-01-01
  • 2012-04-20
  • 1970-01-01
相关资源
最近更新 更多