【问题标题】:Allocating a std::string with std::vector iterators causes debug errors in one project, but works in another?使用 std::vector 迭代器分配 std::string 会导致一个项目中的调试错误,但在另一个项目中有效?
【发布时间】:2013-02-25 07:44:51
【问题描述】:

我正在尝试使用 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::string _name = std::string(data.cbegin(), data.cend()); 的调用堆栈向下 10 级。我检查了向量的值,它有大小为 61。我认为问题出在实际内容上?但是 std::string::value_type 会出现什么问题?GetRawInputDeviceInfo() 返回 true,因此它成功地用字符填充了向量。正如我提到的,我从中读取的教程代码构建并完美运行。对于那些感兴趣的人,这是该项目的链接:The guy stopped updating it, but its almost fully functional

【问题讨论】:

    标签: c++ string memory-management iterator


    【解决方案1】:

    我认为这与以下事实有关:根据您的编译器选项,该字符串应由charwchar_t 组成。因此,您应该使用std::basic_string&lt;TCHAR&gt;,而不是使用std::string。另外,您可能想查看this question and its answers

    【讨论】:

      【解决方案2】:

      我对这个特定的 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);
      

      希望这会有所帮助!

      【讨论】:

      • 也只需将其缩短为:return std::string(data.cbegin(), data.cend()-1);
      猜你喜欢
      • 2014-11-08
      • 2015-04-29
      • 2014-12-12
      • 1970-01-01
      • 2019-09-21
      • 2020-05-04
      • 2019-11-07
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多