C ++: проверить, ссылается ли адрес - PullRequest
2 голосов
/ 06 марта 2012

Есть ли в C ++ способ проверить, не ссылается ли адрес памяти каким-либо указателем?

Ответы [ 5 ]

8 голосов
/ 06 марта 2012

Нет, совсем нет.

(Если, конечно, вы сами не отслеживаете.)

2 голосов
/ 06 марта 2012

Это означало бы, что в C ++ есть сборщик мусора или эквивалент, чего нет.Другими словами, нет.

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

1 голос
/ 06 марта 2012

Это невозможно. Подумайте только об арифметике указателей: из заданной области памяти вы можете увеличивать свой путь и достигать разных мест. Используется для перемещения по массивам: от

int * a = &array[0];

никто не знает, будете ли вы делать ++ a, a + 3 или что-то еще. И вы можете, начиная с массива [0], выходить за пределы массива (который, по сути, не ограничен :-)).

Это глубоко укоренилось в C и унаследованном C ++, но C ++ разработал серию идиоматических стилей, которые пытаются свести к минимуму необходимость перехода на уровень необработанных указателей. Вы можете прочитать об умных указателях (которые ведут подсчет того, кто ссылается на данный ресурс, и удаляют его, когда счетчик обнуляется). Во многих случаях вместо массивов вы можете использовать std :: vector, который дает вам много преимуществ, не заботясь о риске выхода на шаг за конец массива.

0 голосов
/ 06 марта 2012

Нет.На самом деле, нет.Но ...


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


В C ++11, несколько низкоуровневых средств были введены для упрощения создания сборщиков мусора:

  • declare_reachable: объявляет, что объект не может быть переработан

  • undeclare_reachable: объявляет, что объект может быть переработан

  • declare_no_pointers: объявляет, что область памяти не содержит отслеживаемых указателей

  • undeclare_no_pointers: отменяет эффект std::declare_no_pointers

  • pointer_safety: перечисляет модели безопасности указателя

  • get_pointer_safety: возвращает текущую модель безопасности указателя

* declare_no_pointers является подсказкой, что объект содержит только целые / битовые поля / что угодно и без указателей, так что когдасканирование сборщика мусора может быть более точным.Эти знания могут быть использованы в вашем случае.


Однако все это становится жертвой трюков с упаковкой .Например, часто используют тот факт, что 64-битные указатели имеют слишком много битов и используют несколько из них для хранения флагов в указателе.Или, наоборот, использовать полезную нагрузку double NaN для хранения указателя или целочисленного значения.Очевидно, что это не очень хорошо подходит для сканирования памяти в поисках указателей, поскольку сканируемые значения не соответствуют реальным адресам.

Эти приемы интенсивно используются в Clang / LLVM или Javascript движках (V8, SpiderMonkey, ...)например, и вообще в части программного обеспечения, которые действительно заботятся об объеме и скорости памяти.


Таким образом, в общем случае, ни C, ни C ++ не слишком потеряли с памятью, чтобы точнобыть в состоянии знать это.Даже std::shared_ptr не более чем соглашение , и можно случайно сохранить указатель raw в другом месте.

На практике, однако, есть решения для большинства проблемты можешь иметь.Либо с использованием системы типов и нескольких соглашений, либо с использованием сканирования Бома (что должно быть довольно редко ...).Однако это требует более сложного вопроса.

0 голосов
/ 06 марта 2012

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

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