Вопрос

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

Это было полезно?

Решение

Цитирую ваш комментарий:

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

Правильный способ — добавить другой член структуры:указатель на функцию освобождения.

Это не просто статическое и динамическое распределение.Есть несколько возможные распределители, из которых malloc() всего один.

В Unix-подобных системах это может быть:

  • Статическая переменная
  • В стеке
  • В стеке, но динамически распределены (т.е. alloca())
  • В куче, выделенной malloc()
  • В куче, выделенной new
  • В куче, в середине массива, выделенного new[]
  • В куче, внутри структуры, выделенной malloc()
  • В куче, внутри базового класса объекта, выделенного с помощью new
  • Выделено с mmap
  • Выделено с помощью специального распределителя
  • Множество других опций, включая несколько комбинаций и вариаций вышеперечисленных.

В Windows у вас также есть несколько сред выполнения, LocalAlloc, GlobalAlloc, HeapAlloc (с несколькими кучами, которые вы можете легко создать) и так далее.

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

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

Раймонд Чен есть сообщение в блоге об этом (ориентировано на Windows, но концепции везде одинаковы): Выделение и освобождение памяти между границами модулей

Другие советы

ACE делает это повсеместно. Вы можете проверить, как они это делают. В общем, вам, вероятно, не нужно делать это в первую очередь, хотя ...

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

Большинство реализаций libc malloc работают, сохраняя заголовок перед каждым возвращаемым блоком памяти, в котором есть поля (которые будут использоваться вызовом free ()), в которых есть информация о размере блока, а также «магическое» значение. Это магическое значение защищает от случайного удаления пользователем указателя, который не был выделен (или освобождения блока, который был перезаписан пользователем). Она очень специфична для системы, поэтому вам нужно взглянуть на реализацию вашей библиотеки libc, чтобы точно узнать, какое магическое значение было там.

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

Можете ли вы подключиться к самой функции malloc (), как это делают отладчики malloc, используя LD_PRELOAD или что-то еще? Если это так, вы можете сохранить таблицу всех выделенных указателей и использовать это. В противном случае я не уверен. Есть ли способ получить в бухгалтерской информации malloc?

Не как стандартная функция.
Отладочная версия вашей библиотеки malloc может иметь некоторую функцию для этого.

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

1.) Получите файл карты для имеющегося у вас кода.

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

3.) После получения адреса объекта (переменной-указателя) из файла mao в 1.) попытайтесь увидеть, в какой блок попадает этот адрес.у вас может быть какая-то идея.

= AD

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top