указатель void * возвращается из функции - повреждение кучи - PullRequest
1 голос
/ 14 марта 2012

Раньше я только что имел дело с этими типами параметров функции __out, используя malloc, но я пытаюсь изменить свои способы.

В качестве конкретного примера, в классе для управления необработанным вводом GetRawInputDeviceInfo () имеет прототип:

UINT GetRawInputDeviceInfo(HANDLE, UINT, LPVOID, PUINT)

LPVOID - указатель на буфер, содержащий нужную мне информацию. PUINT - указатель на UINT, содержащий размер данных, содержащихся в буфере, на который указывает LPVOID.

Обычно я бы (после заполнения PUINT):

PUINT cbSize; // assume it is sized correctly and contains the proper
              // length of data

LPVOID buffer = (LPVOID)malloc(sizeof(&cbSize));
GetRawInputDeviceInfo(XXX.handle, RIDI_DEVICENAME, buffer, cbSize);
//do something w/buffer
free(buffer);

Теперь, пытаясь сделать это без malloc, я бы написал: (извините, я набираю это с работы, поэтому я могу испортить это по памяти)

PUINT cbsize; // assume it is sized correctly and contains the proper
              // length of data

1 следующего объявления и примеров использования: LPVOID unique_ptr:

std::unique_ptr<LPVOID> buffer;
GetRawInputDeviceInfo(xxx.handle, RIDI_DEVICENAME, buffer.get(),
                      cbSize);

UINT unique_ptr:

std::unique_ptr<UINT> buffer;
GetRawInputDeviceInfo(xxx.handle, RIDI_DEVICENAME,
                      (LPVOID)buffer.get(), cbSize);

Сырой указатель UINT:

UINT *buffer = NULL;
GetRawInputDeviceInfo(xxx.handle, RIDI_DEVICENAME,
                      (LPVOID)buffer, cbSize);

Затем читаем буфер:

OutputDebugString((LPCSTR)buffer) //add .get() for unique_ptr

Дело в том, что буфер содержит информацию, которую я хочу, и выводится так, как должно быть! Однако, когда unique_ptr выходит из области видимости и удаляется (или удаляется UINT *), я получаю исключение повреждения кучи. Я прошел по коду и в результате выполнения функции GetRawInputDeviceInfo все мои контейнеры / переменные уровня класса перезаписывают свои данные. Например, приведенная выше последовательность появляется в цикле for, и мой итератор переходит от 0 (первая итерация) к 80837436 (или около того), и все остальные переменные локальные переменные перепутаны.

Итак, как я могу получить информацию в буфере, не испортив все остальное? И желательно без использования malloc / free и с духом RAII :))

1 Ответ

3 голосов
/ 14 марта 2012

Правильный способ использования GetRawInputDeviceInfo -

  1. Получить количество символов, которое содержит имя

    UINT char_count;
    GetRawInputDeviceInfo(xxx.handle, RIDI_DEVICENAME, NULL, &char_count);
    
  2. Выделите достаточно длинный строковый буфер и получите имя

    std::unique_ptr<wchar_t[]> buf (new wchar_t[char_count]);
    GetRawInputDeviceInfo(xxx.handle, RIDI_DEVICENAME, buf.get(), &char_count);
    

Ваш пример кода не вызовет повреждения кучи. Вероятно, ваш реальный код использует неинициализированный buffer, который заставил GetRawInputDeviceInfo записать данные в какое-то непреднамеренное место.

...