Определение, является ли указатель действительным - PullRequest
12 голосов
/ 04 января 2011

По моим наблюдениям, если вызывается free( ptr ), где ptr не является действительным указателем на выделенную системой память, происходит нарушение доступа.Допустим, я звоню free следующим образом:

LPVOID ptr = (LPVOID)0x12345678;
free( ptr );

Это определенно приведет к нарушению доступа.Есть ли способ проверить, что область памяти, на которую указывает ptr, является действительной выделенной системой памятью?

Мне кажется, что часть управления памятью ядра ОС Windows должна знать, какая память былавыделяется и какая память остается для выделения.Иначе как он мог узнать, достаточно ли памяти для выполнения данного запроса? (риторический) При этом представляется разумным заключить, что должна существовать функция (или набор функций), которая позволила бы пользователю определить, является ли указатель действительной памятью, выделенной системой.Возможно, Microsoft не обнародовала эти функции.Если Microsoft не предоставила такой API, я могу только предположить, что это было сделано по преднамеренной и конкретной причине.Принесет ли такая зацепка в систему значительную угрозу безопасности системы?

Ситуационный отчет

Хотя знание того, является ли указатель памяти действительным, может быть полезным во многих сценарияхЭто моя конкретная ситуация:

Я пишу драйвер для нового оборудования, которое должно заменить существующее оборудование, которое подключается к ПК через USB.Мой мандат состоит в том, чтобы написать новый драйвер так, чтобы обращения к существующему API для текущего драйвера продолжали работать в приложениях для ПК, в которых он используется.Таким образом, единственными необходимыми изменениями в существующих приложениях является загрузка соответствующих DLL драйверов при запуске.Проблема в том, что существующий драйвер использует обратный вызов для отправки полученных последовательных сообщений в приложение;указатель на выделенную память, содержащую сообщение, передается от драйвера к приложению посредством обратного вызова.В этом случае приложение несет ответственность за вызов другого API драйвера для освобождения памяти путем передачи того же указателя из приложения в драйвер.В этом сценарии второй API не может определить, действительно ли приложение вернуло указатель на действительную память.

Ответы [ 13 ]

1 голос
/ 04 января 2011

Не без доступа к внутренним компонентам реализации malloc.

Возможно, вы могли бы определить некоторые недопустимые указатели (например, те, которые нигде не указывают в пространстве виртуальной памяти вашего процесса), но если вы возьмете действительный указатель и добавите к нему 1, он будет недействительным для вызова free() но все равно будет указывать на выделенную системой память. (Не говоря уже об обычной проблеме вызова free по одному и тому же указателю более одного раза).

0 голосов
/ 04 января 2011

C ++ не использует 'malloc', но 'new', который обычно имеет другую реализацию; следовательно, «delete» и «free» не могут быть смешаны - ни «delete», ни «delete []» (его версия-массив)

DLL имеют собственную область памяти и не могут быть смешаны с системой управления памятью области памяти без DLL.

Каждый API и язык имеет свое собственное управление памятью для своего типа объектов памяти. Т.е .: Вы не 'free ()' и не 'удаляете' открытые файлы, вы 'закрываете ()' их. То же самое относится и к другим API, даже если тип является указателем на память, а не дескриптором.

0 голосов
/ 04 января 2011

Почему 0x12345678 обязательно будет недействительным?Если ваша программа использует много памяти, там может быть что-то выделено.Действительно, существует только одно значение указателя, на которое вы должны полностью полагаться, чтобы быть недопустимым распределением: NULL.

...