【问题标题】:MSVC: Compiler bug on seemingly trivial C code?MSVC:看似微不足道的 C 代码的编译器错误?
【发布时间】:2011-06-07 00:35:37
【问题描述】:

这是一个简单的45 line console application,它重现了我的 Win XP 32 位系统上的错误。

相关部分:

input_watcher_wndproc 属于一个通过 RegisterRawInputDevices 设置的窗口,用于观察原始键盘输入事件。

  LRESULT APIENTRY
  input_watcher_wndproc(HWND hwnd, UINT umsg, WPARAM wparam, LPARAM lparam) {
    switch(umsg) {
    case WM_INPUT:
      analyze_raw_input((HRAWINPUT)lparam);
      DefWindowProc(hwnd, umsg, wparam, lparam);
      return 0;
    }
    return DefWindowProc(hwnd, umsg, wparam, lparam);
  }

  void analyze_raw_input(HRAWINPUT raw_input) {
    RAWINPUTHEADER header;
    UINT size;
    GetRawInputData(raw_input, RID_HEADER, &header, &size, sizeof(RAWINPUTHEADER));
    printf("raw input device handle: %d\n", header.hDevice);
  }

使用 MSVC 9 或 10 编译时,程序总是错误地将设备句柄报告为“1”。

但是,如果我应用一些看似非功能性的更改,例如将 switch 语句转换为 if 语句...

    if (umsg == WM_INPUT) {
      analyze_raw_input((HRAWINPUT)lparam);
      DefWindowProc(hwnd, umsg, wparam, lparam);
      return 0;
    }

...或者在调用analyze_raw_input之前添加任意指令时...

  switch(umsg) {
   case WM_INPUT:
     puts("foo");
     analyze_raw_input((HRAWINPUT)lparam);
     DefWindowProc(hwnd, umsg, wparam, lparam);
     return 0;
   }

...代码运行良好并输出正确的设备句柄。

这是修改后的工作 source code,只添加了打印语句。

有什么可能导致这种行为的想法吗?

【问题讨论】:

  • 在调用 GetRawInputData 之前尝试将 size 初始化为 sizeof(RAWINPUTHEADER)
  • 完美,谢谢!我不敢相信我错过了这个。我在哪里可以了解更多关于此类错误的幕后情况?
  • 每当添加或移动代码改变行为时,我总是怀疑初始化或内存践踏。当我查看GetRawInputData 的文档时,我看到 pcbSize 是 __inout 并且该大小没有初始化,所以......
  • @ribram:眼睛不错。你应该把它作为一个答案,这样它才能被接受。

标签: visual-studio winapi visual-c++


【解决方案1】:

确保在调用 GetRawInputData 之前将 'size' 初始化为 sizeof(RAWINPUTHEADER),因为这是一个 __inout 参数。

【讨论】:

  • 并检查GetRawInputData之类的函数调用的返回值,这将帮助您发现这样的错误。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-10-17
  • 2011-06-04
  • 1970-01-01
  • 2010-10-18
  • 2020-05-21
  • 1970-01-01
  • 2021-05-28
相关资源
最近更新 更多