Проверка, выделен ли определенный адрес в памяти - PullRequest
1 голос
/ 19 января 2012

У меня есть функция, которая получает указатель на динамический массив 100 дюймов. Но вместо 100 у меня есть только 50, выделенных malloc или calloc до этого.

Есть ли способ, которым я мог бы проверить, выделен ли какой-либо элемент (например, 79-й), а не задаться вопросом, что на самом деле означает этот SIGSEGV?

Мой вопрос чисто теоретический, и у меня нет действительного кода для показа.

Ответы [ 5 ]

4 голосов
/ 19 января 2012

Нет, указатель не сохраняет свой размер. Возможно, вам лучше сохранить размер и указатель в структуре и передать вместо этого:

typedef struct
{
    size_t size;
    int *ptr;
}  my_data;
void myFunc(my_data *data)
{
    size_t i;
    for(i = 0; i < data->size; i++)
    {
        // data->ptr[i];
    }
}
void myFunc2(my_data *data, size_t index)
{
    if(index < data->size)
    {
        // memory location exists
    }
}
1 голос
/ 19 января 2012

Ну, вы могли бы сделать это в соответствии с вашим описанием, учитывая массив и ища индекс (который немного отличается от "любого необработанного указателя"). А если еще немного поработать, то можно сделать такую ​​вещь для любого указателя.

Функция malloc обязательно хранит информацию о том, сколько было выделено. К сожалению, нет никакого стандарта, как это должно быть сделано. Некоторые компиляторы перераспределяют и сохраняют размер, непосредственно предшествующий выделенным данным. Другие могут хранить адреса на карте, а другие могут делать что-то еще, вы не знаете.

Однако большинство (все?) Библиотек C и, по крайней мере, один из известных мне компоновщиков имеют явную поддержку перегрузки / перехвата / замены функций выделения.
Например, в библиотеке GNU C вы можете установить __malloc_hook. и GNU ld позволяет вам делать это на уровне компоновщика с __wrap_malloc.

Таким образом, вы можете перегрузить / перехватить malloc и free с помощью функции, которая просто вызывает действительную функцию malloc и хранит информацию о том, сколько было выделено вам где-то (например, путем перераспределения и использования первого слова, или как угодно).

Затем напишите функцию, которая получает базовый указатель и индекс. Эта функция просматривает информацию о распределении (теперь вы знаете, где ее найти!) И может тривиально проверить, находится ли индекс в диапазоне. Это не работает для «просто любого указателя».

Альтернативное решение, которое работает для «просто любого указателя», состоит в том, чтобы написать распределитель, который удовлетворяет выделениям из отдельных арен, а не просто заключать в реальность malloc. Все распределения, приходящие с одной и той же арены, имеют одинаковый размер распределения. Учитывая любой указатель, вам нужно будет всего лишь перебрать все ваши арены и посмотреть, находится ли адрес в пределах начального и конечного адреса арены.

Однако, как правило, нужно быть полностью уверенным в том, сколько он выделил, это не должно быть догадкой, случайной удачей или чем-то, что нужно выяснить во время выполнения.
Кроме того, учитывая наличие готовых к использованию отладчиков памяти, я сомневаюсь, что действительно стоит потратить время на выполнение таких задач на стороне приложения. Просто используйте что-то вроде valgrind, вообще не нужно писать никакого кода.

1 голос
/ 19 января 2012

Несколько лет назад я использовал одну библиотеку, я забыл ее название.Используя его, вы можете создать блок try-catch и попытаться получить доступ к неизвестным данным, например, x [79] в блоке try, и, если в нем не выделена память, сгенерировано исключение.

1 голос
/ 19 января 2012

Нет, нет.

Это когда вы отключаете инструмент динамического анализа (например, valgrind ) или используете реальный контейнер, в котором хранится информация о его размере.

1 голос
/ 19 января 2012

Нет, в коде нет портативного и надежного способа проверить это.

Существуют инструменты, такие как valgrind, которые могут помочь диагностировать определенные типы ошибок памяти.

...