Как очистить удаленные объекты в C ++ -- c++ пол Связанный проблема

how do clean up deleted objects in C++


7
vote

проблема

русский

Возможно ли использовать память об удаленных объектах в C ++? Я хочу сделать это, чтобы воспроизвести Coredump в модульном тесте:

 <код> //Some member variable of object-b is passed-by-pointer to object-a //When object-b is deleted, that member variable is also deleted //In my unit test code, I want to reproduce this //even if I explicitly call delete on object-b //accessBMemberVariable should coredump, but it doesn't //I'm assuming even though object-b is deleted, it's still intact in memory A *a = new A(); {   B *b = new B(a);   delete b; } a->accessBMemberVariable();   
Английский оригинал

Is it possible to zero out the memory of deleted objects in C++? I want to do this to reproduce a coredump in unit test:

//Some member variable of object-b is passed-by-pointer to object-a //When object-b is deleted, that member variable is also deleted //In my unit test code, I want to reproduce this //even if I explicitly call delete on object-b //accessBMemberVariable should coredump, but it doesn't //I'm assuming even though object-b is deleted, it's still intact in memory A *a = new A(); {   B *b = new B(a);   delete b; } a->accessBMemberVariable(); 
</div
  

Список ответов

20
 
vote
vote
Лучший ответ
 

Вы, вероятно, должны переопределить <код> delete оператора.

Пример для данного класса B:

 <код> class B { public:    // your code   ...    // override delete   void operator delete(void * p, size_t s)   {     ::memset(p, 0, s);     ::operator delete(p, s);   } };   

Редактировать: спасибо litb для указания этого.

 

You probably should override the delete operator.

Example for the given class B:

class B { public:    // your code   ...    // override delete   void operator delete(void * p, size_t s)   {     ::memset(p, 0, s);     ::operator delete(p, s);   } }; 

EDIT: Thanks litb for pointing this out.

</div
 
 
     
     
3
 
vote

AccessbmemberVariable должен Coredump, но это не

Нах, почему это должно? Вполне возможно, что память, которую B используемую, используемую, теперь принадлежит ЭЛТ, который владеет вашему приложению. ЭЛТ может выбрать не отпустить память обратно в ОС. Core Dumps произойдет только в том случае, если вы несете доступа к памяти не , принадлежащие вашему приложению.

Обнуление памяти, занятой B, может не делать вам никакой пользы в зависимости от типа переменной, который A имеет адрес.

Мой совет будет выделен B на стеке, что следует выставить фейерверки ... но потом опять же, не совсем так, как вы ожидаете ...

Так что, если вы действительно хотите, чтобы ядра выплата, вы должны использовать функции ОС, чтобы выделить память и освободить его:

 <код> char *buf = OS_Alloc(sizeof(B)); B *b = new(buf) B(); a->someBMember = &b->myMember; b->~B(); OS_Free(buf); a->accessBMemberVariable();   
 

accessBMemberVariable should coredump, but it doesn't

Nah, why should it? It's quite possible that the memory that b used to occupy is now owned by the CRT, the CRT that your application owns. The CRT may opt to not release memory back to the OS. Core dumps will only happen if you access memory not owned by your application.

Zeroing out the memory occupied by b may not do you any good depending on the type of variable that A has the address of.

My advice would be to allocate B on the stack, that should bring out the fireworks... but then again, not quite in the way you'd expect...

So if you really want a core dump you should use the OS functions to allocate memory and free it:

char *buf = OS_Alloc(sizeof(B)); B *b = new(buf) B(); a->someBMember = &b->myMember; b->~B(); OS_Free(buf); a->accessBMemberVariable(); 
</div
 
 
2
 
vote

Другой постер предлагается:

 <код>  delete b;  memset(b,0,sizeof(B));   

Пожалуйста, не делайте этого !!! Пишетки для решения пространства, которое возвращается в Memory Manager, не определены !!!!

Даже если ваш компилятор и библиотека позволяют вам уйти с ним, это плохо плохо. Изменение в библиотеке или платформе или даже обновление в компиляторе укусит вас в заднице.

Подумайте о состоянии гонки, где вы удаляете B, то какой-то другой поток делает распределение, память в B выдается, а затем вы называете MEMSSET! Взрыв, ты мертв.

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

 <код>  memset(b,0,sizeof(B));  delete b;   
 

Another poster suggested:

 delete b;  memset(b,0,sizeof(B)); 

Please don't do this!!! Writes to address space that is returned to the memory manager are UNDEFINED!!!!

Even if your compiler and library let you get away with it now, it is bad bad bad. A change in library or platform, or even an update in the compiler will bite you in the ass.

Think of a race condition where you delete b, then some other thread makes an allocation, the memory at b is given out, and then you call memset! Bang, you're dead.

If you must clear the memory (which who cares) zero it out before calling delete.

 memset(b,0,sizeof(B));  delete b; 
</div
 
 
       
       
2
 
vote

Используйте размещение «новое», если вы можете ( http: //www.parashift.com/c++-faq-lite/dtors.html#faq-11.10 ) И нулевой чан, который вы дали после вызова предмета деструктора вручную.

 

Use placement "new" if you can (http://www.parashift.com/c++-faq-lite/dtors.html#faq-11.10) and zero out the chunk you gave after calling the object destructor manually.

</div
 
 
1
 
vote

Используйте отладку MALLOC / новые функции в вашей среде.

на MSVC, ссылка с библиотеками выполнения отладки. На FreeBSD установите Malloc_Options, чтобы иметь флаги «Z» или «J», в зависимости от ситуации. На других платформах прочитайте документацию или замените в соответствующем распределите с поддержкой отладки.

Вызов memset () После удаления просто плохо на так много уровней.

 

Use the debugging malloc/new features in your environment.

On MSVC, link with the debug runtime libraries. On FreeBSD, set MALLOC_OPTIONS to have the 'Z' or 'J' flags, as appropriate. On other platforms, read the documentation or substitute in an appropriate allocator with debugging support.

Calling memset() after deletion is just bad on so many levels.

</div
 
 
0
 
vote

В вашем примере вы пишете

'a- & gt; accessbmumbembervariable' Это опечатка? Разве это не должно быть «A- & GT; AccessBumbervariable»?

Предполагая, что это опечатка (в противном случае весь дизайн кажется немного странным).

Если вы хотите убедиться, что «A» удаляется правильно, он, вероятно, лучше вместо этого измените способ обрабатывать распределение и вместо этого использовать AUTO_PTR. Таким образом, вы будете уверены, что все удалены правильно:

 <код> auto_ptr<A> a( new A ); {   auto_ptr<B> b( new B(a) ); // B takes ownership of 'a', delete at scope exit } a->accessBMemberVariable(); // shouldn't do to well.   

и конструктор для b в форме

 <код> B( auto_ptr<A>& a ) : m_a(a) {;}   

Где

 <код> auto_ptr<A> m_a   
 

In your example you write

'A->accessBMemberVariable' is this a typo? shouldn't it be 'a->accessBMemberVariable' ?

Assuming it is a typo (otherwise the whole design seems a bit weird).

If you want to verify that 'a' is deleted properly it probably be better to instead change the way you handle the allocation and use auto_ptr's instead. That way you will be sure things are deleted properly:

auto_ptr<A> a( new A ); {   auto_ptr<B> b( new B(a) ); // B takes ownership of 'a', delete at scope exit } a->accessBMemberVariable(); // shouldn't do to well. 

and a constructor for B in the form of

B( auto_ptr<A>& a ) : m_a(a) {;} 

where

auto_ptr<A> m_a 
</div
 
 
-3
 
vote

Как только вы удалили <код> b у вас на самом деле нет разрешения на запись там, где это было. Но вы обычно можете уйти с этим; И вы увидите код, где программисты используют <код> memset для этого.


Одобренный способ сделать это, однако, будет называть деструктора напрямую, то писать через память (с, скажем, <код> memset ), а затем вызовите <код> delete на объекте. Это требует, чтобы ваш деструктор был довольно умным, потому что <код> delete собирается вызвать деструктор. Таким образом, деструктор должен понимать, что весь объект не только memset(b,0,sizeof(B)); delete b; 0 's и ничего не делать:

 <код>  memset(b,0,sizeof(B));  delete b; 1  
 

Once you've deleted b you don't really have permission to write over where it was. But you usually can get away with doing just that; and you'll see code where programmers use memset for this.


The approved way to do this, though, would be to call the destructor directly, then write over the memory (with, say, memset) and then call delete on the object. This does require your destructor to be pretty smart because delete is going to call the destructor. So the destructor must realize that the whole object is nothing but 0's and not do anything:

b->~B(); memset(b, 0, sizeof(b)); delete b; 
</div
 
 
     
     

Связанный проблема

1  Наличие проблемных проектов C ++ в Eclipse CDT в ОС X для глупой причины  ( Having trouble building c project in eclipse cdt in os x for a silly reason ) 
Я пытаюсь построить очень простую программу C ++ в Eclipse, и я получаю очень глупую ошибку: <код> **** Internal Builder is used for build **...

-2  Конструкторы ведут себя странным с кодом обработки исключений  ( Constructors behaving strange with exception handling code ) 
Скриншот # 1: Образец (образец & amp;) {...) // Нет ошибки без использования "const" Скриншот № 2: Destructor называется дважды, когда Copy-Constructor не вк...

-1  Qt показывает изображение на 1/4 секунды  ( Qt show an image for 1 4 of a second ) 
Эй, я пробовал несколько раз, чтобы завершить это, используя Uslep или Qt Sleep, когда показывает изображение, но иногда (почти каждый раз) он появляется белы...

3  Отправка HTTP Post Запрос на обновление содержимого файла с использованием C ++ REST SDK Casablanca  ( Sending a http post request for updating file contents using c rest sdk casabl ) 
Я пытаюсь обновить содержимое файла на сервере Alfresco, используя C ++ SDK SDK. Я использую URL Alfresco CMIS URL для отправки запроса. Быть более конкретным...

0  Использование Pybind11 на MacBook Pro  ( Using pybind11 on macbook pro ) 
Я пытаюсь использовать Pybind11 на MacBook, и я пытаюсь сделать так, как было написано в https://pybind11.readtheDocs.io/en/stable/basics.html я установил C...

29  Добавление! Оператор и SQRT (), POW () и т. Д. Для пример примерка калькулятора  ( Adding the operator and sqrt pow etc to a calculator example applicatio ) 
Я делаю упражнения в новой книге Strustrup "Принципы программирования и практики с использованием C ++" и было интересно, если кто-нибудь на переполнении ст...

145  Как определить, является ли строка номер с C ++?  ( How to determine if a string is a number with c ) 
У меня было довольно неприятностей, пытаясь написать функцию, которая проверяет, является ли строка номер. Для игры, которую я пишу, мне просто нужно проверит...

4  Строка :: Новая: что это?  ( Stringnew what is it ) 
Я из фона Java и изучает C ++. Я столкнулся с следующим C ++: <код> String source = String::New("'Hello' + ', World'"); Как то, что я так понимаю, это ...

-1  C ++ с использованием класса от заголовка в классе  ( C using a class from a header within a class ) 
У меня есть немного проблемы с классами, используемыми в классах, из файлов заголовка. У меня есть время занятий во времени. Как: <код> #ifndef TIME_H #de...

3  Преобразование IPlimage в вектор в 1D в OpenCV  ( Converting iplimage into 1d vector in opencv ) 
Я хочу преобразовать MXN IPLIMAGE в вектору A (M * N) x 1 1. Может ли это сделать с любой функцией в OpenCV? Любая помощь значительно ценится. ...

42  Как я могу легко увидеть график C / C ++ #include? [закрыто]  ( How can i see the c c include graph easily ) 
<в сторону CLASS = "S-NEWACTS S-WELTIVE__info JS-Post-New Imide MB16« Роль = «Статус»> закрыт. Этот вопрос не соответствует Рекомендациям переполнения ...

1  Как работают Char и INT в C ++  ( How do char and int work in c ) 
Может быть, я собираюсь задать глупый вопрос, но я хочу подтвердить, как работает Char? Позвольте мне объяснить с примерами того, что я хочу спросить. Пусть п...

29  C ++ Указатель на объекты  ( C pointer to objects ) 
в C ++ У вас всегда инициализировать указатель на объект с new ключевое слово? или вы просто имеете это тоже: <код> MyClass *myclass; myclass->DoSometh...

7  Используйте простой класс C ++ в Android NDK  ( Use a simple c class in android ndk ) 
Я пытаюсь узнать основные основы Android NDK, но я застрял, когда я должен использовать его с классом C ++. Я понимаю, как использовать его с помощью просто...

1  Проблема с использованием TextureView с NDK  ( Issue using textureview with ndk ) 
Я работаю над небольшим кусочком кода, используя текстуру, чтобы отобразить результат среды MediaPlayer. Я сталкиваюсь с проблемой, пытающимся смешивать упр...