#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 не требует от вас использования такого количества указателей, и их использование должно быть частью вашего дизайна.