Тестирование указателей на валидность (C / C ++) - PullRequest
78 голосов
/ 15 февраля 2009

Есть ли способ определить (программно, конечно), является ли данный указатель "действительным"? Проверить NULL легко, но как насчет таких вещей, как 0x00001234? При попытке разыменования этого типа указателя возникает исключение / сбой.

Кроссплатформенный метод предпочтительнее, но также подходит для конкретной платформы (для Windows и Linux).

Обновление для уточнения: Проблема не в устаревших / освобожденных / неинициализированных указателях; вместо этого я реализую API, который получает указатели от вызывающей стороны (например, указатель на строку, дескриптор файла и т. д.). Вызывающая сторона может отправить (намеренно или по ошибке) неверное значение в качестве указателя. Как предотвратить сбой?

Ответы [ 28 ]

0 голосов
/ 01 сентября 2015

Следующее работает в Windows (кто-то предлагал это раньше):

 static void copy(void * target, const void* source, int size)
 {
     __try
     {
         CopyMemory(target, source, size);
     }
     __except(EXCEPTION_EXECUTE_HANDLER)
     {
         doSomething(--whatever--);
     }
 }

Функция должна быть статическим, автономным или статическим методом некоторого класса. Чтобы проверить только для чтения, скопируйте данные в локальный буфер. Чтобы проверить запись без изменения содержимого, запишите их поверх. Вы можете проверить только первые / последние адреса. Если указатель недействителен, управление будет передано в doSomething, а затем за скобками. Только не используйте ничего, что требует деструкторов, таких как CString.

0 голосов
/ 15 февраля 2009

IsBadReadPtr (), IsBadWritePtr (), IsBadCodePtr (), IsBadStringPtr () для Windows.
Это занимает время, пропорциональное длине блока, поэтому для проверки работоспособности я просто проверяю начальный адрес.

0 голосов
/ 12 апреля 2014

эти ссылки могут быть полезны

_CrtIsValidPointer Проверяет, что указанный диапазон памяти действителен для чтения и записи (только для отладочной версии). http://msdn.microsoft.com/en-us/library/0w1ekd5e.aspx

_CrtCheckMemory Подтверждает целостность блоков памяти, выделенных в куче отладки (только в версии отладки). http://msdn.microsoft.com/en-us/library/e73x0s4b.aspx

0 голосов
/ 17 марта 2014

вам следует избегать этих методов, потому что они не работают. blogs.msdn.com/oldnewthing/archive/2006/09/27/773741.aspx - JaredPar 15 февраля 2009 г. в 16: 02

Если они не работают - следующее обновление Windows это исправит? Если они не работают на концептуальном уровне - функция, вероятно, будет полностью удалена из windows api.

В документации MSDN утверждается, что они запрещены, и причиной этого, вероятно, является недостаток дальнейшей разработки приложения (например, обычно вы не должны молча есть неверные указатели - если вы, конечно, отвечаете за разработку всего приложения), производительность / время проверки указателя.

Но вы не должны утверждать, что они не работают из-за какого-то блога. В своем тестовом приложении я убедился, что они работают.

0 голосов
/ 15 февраля 2009

Я видел, как различные библиотеки используют какой-то метод для проверки памяти без ссылок и тому подобное. Я считаю, что они просто «переопределяют» методы выделения и освобождения памяти (malloc / free), в которых есть некоторая логика, которая отслеживает указатели. Я полагаю, это излишне для вашего случая использования, но это был бы один из способов сделать это.

0 голосов
/ 09 марта 2009

Вы знаете, что новый драйвер (по крайней мере для Linux), способный на это, вероятно, будет не так сложно написать.

С другой стороны, было бы глупо создавать такие программы, как эта. Если у вас нет действительно специфического и одноразового использования для такой вещи, я бы не рекомендовал это. Если вы создали большое приложение, загруженное постоянными проверками правильности указателя, оно, вероятно, будет ужасно медленным.

0 голосов
/ 18 февраля 2009

Приложение к принятому ответу (ответам):

Предположим, что ваш указатель может содержать только три значения - 0, 1 и -1, где 1 означает действительный указатель, -1 недопустимый и 0 другой недопустимый. Какова вероятность того, что ваш указатель равен NULL, все значения одинаково вероятны? 1/3. Теперь возьмите действительный случай, поэтому для каждого неправильного случая у вас есть соотношение 50:50, чтобы перехватить все ошибки. Выглядит хорошо, правда? Масштабируйте это для 4-байтового указателя. Есть 2 ^ 32 или 4294967294 возможных значений. Из них только ОДНО значение является правильным, одно - ПУСТО (NULL), и у вас все еще остается 4294967292 других недопустимых случая. Пересчитать: у вас есть тест на 1 из (4294967292+ 1) недействительных случаев. Вероятность 2.xe-10 или 0 для большинства практических целей. Такова бесполезность проверки NULL.

0 голосов
/ 15 февраля 2009

Технически вы можете переопределить оператор new delete ) и собрать информацию обо всей выделенной памяти, чтобы вы могли иметь способ проверить, является ли память кучи действительной. но:

  1. вам все еще нужен способ проверить, расположен ли указатель на стеке ()

  2. вам необходимо определить, что является «действительным» указателем:

а) память по этому адресу выделено

б) память по этому адресу начальный адрес объекта (например, адрес не в середине огромного массив) * * тысяча двадцать-одна

в) память по этому адресу начальный адрес объекта ожидаемый тип

Итог : рассматриваемый подход не является способом C ++, вам нужно определить некоторые правила, которые гарантируют, что функция получает действительные указатели.

...