Проверка, если что-то было неправильно - PullRequest
8 голосов
/ 10 ноября 2008

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

Ответы [ 8 ]

11 голосов
/ 10 ноября 2008

Цитата из вашего комментария:

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

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

Это не просто статическое или динамическое распределение. Существует несколько возможных распределителей, из которых malloc() - это только один.

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

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

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

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

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

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

2 голосов
/ 10 ноября 2008

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

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

2 голосов
/ 10 ноября 2008

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

2 голосов
/ 10 ноября 2008

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

0 голосов
/ 10 ноября 2008

1.) Получите файл карты для кода, который у вас есть.

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

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

= AD

0 голосов
/ 10 ноября 2008

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

0 голосов
/ 10 ноября 2008

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

0 голосов
/ 10 ноября 2008

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...