Отслеживание всего недопустимого использования памяти?

#c #visual-c

#c #visual-c

Вопрос:

В Visual C иногда, когда ресурс был уничтожен, к нему все еще можно «получить доступ» через что-либо, указывающее на эту ячейку памяти (хотя и очень ненадежно / стабильно). Есть ли способ заставить VC возвращать исключение / сообщение / и т.д., Которое предупреждало бы о таком нестабильном использовании?

Например:

 int *c = new int(5);
delete c;
std::cout << *c << std::endl; // will execute, however the value is likely to be invalid
  

По слегка связанному вопросу, сталкиваются ли системы Linux с такой же проблемой, или это приведет к segfault?

Комментарии:

1. заставляет меня задуматься, существует ли такая модель ссылочного указателя, которая не подсчитывается по ссылкам, а имеет вид «ведущий / ведомый», т. Е. удаление одной ссылки делает недействительными все остальные?

2. @davka : Почитайте о std::weak_ptr .

Ответ №1:

Не использовать необработанные указатели? Использование shared_ptr / unique_ptr или стандартных контейнеров или ptr-контейнеров boost действительно уменьшит ваши new / delete проблемы. Также пересмотрите свой дизайн и постарайтесь максимально свести к минимуму паутину указателей между объектами. Используйте weak_ptr , когда сможете.

Но чтобы ответить на ваш вопрос более прямо: надежного способа нет. Доступ к удаленному элементу — это неопределенное поведение, и поэтому все является игрой. Лучше всего использовать MS debug malloc или, скажем, valgrind или другую проверку памяти. Проблемы с кучей и памятью трудно отлаживать.

РЕДАКТИРОВАТЬ: это неопределенное поведение, поэтому системы Linux снова могут получить или не получить ошибку segfault.

ПРАВКА2: согласно http://msdn.microsoft.com/en-us/library/2f7sy2e9(v=vs.80).aspx вы определяете _DEBUG в сочетании с использованием библиотеки debug CRT для включения функций debug heap.

Изначально я не упоминал Purify из-за его стоимости, но в прошлом мне с ним довольно везло.

Комментарии:

1. Как мне это сделать (использовать debug malloc)? Я настроил свою сборку на debug, но она будет продолжать использовать обычный malloc.

2. Для Windows эквивалентом Valgrind было бы Rational Purify

Ответ №2:

 int *c = new int(5);
delete c;
c = null;  //add this
  

Комментарии:

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

2. Это не сработало бы даже для этого примера. Разыменование удаленного указателя вызывает неопределенное поведение, даже если вы это сделаете c=NULL .

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

Ответ №3:

Доступны сторонние инструменты: для Visual C есть Purify (но это дорого) и, возможно, некоторые другие инструменты. (В Linux есть Valgrind, но я не думаю, что он доступен для Windows.) В остальном дизайн — ваш лучший друг. C не требует от вас использования такого количества указателей, и их использование должно быть частью вашего дизайна.