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()で何が問題になる可能性があるので、正常に入力されました。ベクトルをcharsでアップしますそして私が言ったように、私がそれを読んだチュートリアルコードはビルドされて完全に実行されました興味のある人のために、ここにプロジェクトへのリンクがあります:男はそれを更新しなくなりましたが、ほぼ完全に機能します

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 が常に完全に動作するとは限りません。

(私の理論が正しければ)あなたが提供しているバッファは1文字しか短すぎないので、ある条件(stl実装、コンパイラ、メモリ条件など)では正常に動作し、他の条件ではうまく動作しない可能性は十分にあります。メモリの破損は一貫した結果をもたらしません。

std::stringこれでブレークポイントが回避される場合は、文字列の一部として、結果の末尾に \0 が含まれることを忘れないでください。それが望ましくない場合は、これも修正してください。

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

お役に立てれば!

于 2013-02-25T08:03:49.463 に答える