0

我正在尝试使用 RawInput API 获取输入设备的名称,但是在分配名称字符串时出现了一个奇怪的错误。基本上我在另一个项目中看到了它,它运行良好。这是有缺陷的代码:

std::string Input::GetDeviceName(void* device)
{
    size_t size;

    bool result = GetRawInputDeviceInfo(device, RIDI_DEVICENAME, null, &size) ;
    if(result < 0)
    {
        throw RawInputException(GetLastError(), L"GetRawInputDeviceInfo(InputDeviceDataRequest::Name)");
    }

    std::vector<std::string::value_type> data(size);

    result = GetRawInputDeviceInfo(device, RIDI_DEVICENAME, &data[0], &size);
    if(result < 0)
    {
        throw RawInputException(GetLastError(), L"GetRawInputDeviceInfo(InputDeviceDataRequest::Name)");
    }
    std::string name = std::string(data.cbegin(), data.cend());
    return(name);
}

相同的代码在我从中读取的教程实现中运行良好,但是当我使用它时,它会在*HeapAlloc(_crtheap, 0, size ? size : 1);*处触发断点,从std的调用堆栈向下 10 级: :string _name = std::string(data.cbegin(), data.cend()); .我检查了向量的值,它的大小为 61。我认为问题出在实际内容上?但是 std::string::value_type 会出现什么问题?GetRawInputDeviceInfo() 返回 true,所以它成功填充用字符向上矢量。正如我所提到的,我从中读取它的教程代码构建并完美运行。对于那些感兴趣的人,这里是项目的链接:这家伙停止更新它,但它几乎功能齐全

4

2 回答 2

1

我认为这与以下事实有关,即根据您的编译器选项,字符串应该由char或组成wchar_t。因此,std::string您应该使用std::basic_string<TCHAR>. 此外,您可能想查看这个问题及其答案

于 2013-02-25T10:42:37.943 回答
0

我对这个特定的 API 不是很熟悉,但试试看:

std::vector<std::string::value_type> data(size+1);

如果这阻止了断点,那么这是因为 GetRawInputDeviceInfo 以 \0 终止字符串,但不将其包含在计数中。如果是这样,它正在写入超出您分配的空间的末尾,可能会破坏堆。大多数 MS API 都不是这样工作的,但我确实发现它们的 API 并不总是表现完美。

由于(如果我的理论是正确的)您提供的缓冲区只有一个字符太短,因此它很可能在某些条件下(stl 实现、编译器、内存条件等)可以正常工作,而在其他条件下则不行。内存损坏没有一致的结果。

如果这确实避免了断点,请不要忘记您的结果std::string将在末尾有一个 \0 作为字符串的一部分。如果你不想这样,也解决这个问题:

std::string name = std::string(data.cbegin(), data.cend()-1);

希望这可以帮助!

于 2013-02-25T08:03:49.463 回答