Например проверять объект при очищении контейнера:
#include <vector>
#include <string>
#include <iostream>
using namespace std;
int main(int argc, char *argv[])
{
vector<string*> vec;
vec.push_back(new string{"ptr1"});
vec.push_back(new string{"ptr2"});
string str1{"nonptr1"};
string str2{"nonptr2"};
vec.push_back(&str1);
vec.push_back(&str2);
for(auto* s : vec) {
cout << *s << endl;
delete s; //На третьем элементе очевидно всё повалится
}
return 0;
}
Есть ли стандартные механизмы определения, каким способом создан объект?
Определить , что адрес в стеке можно с помощью проверки адреса:
bool isInStack(void * x) {
volatile bool stacktop ;
return x > ( & stacktop ) ; }
Но проблема с другими адресами: глобальных переменных. У них адреса не в стеке , а в куче. И определить, что нужно удалять или нельзя придётся вручную, задавая вектор структуры с флагом , что нужно удалить. Данный способ определять место информации , что оно стеке очень ИНДИВИДУАЛЬНЫЙ. Это называется ХАКИНГ. Где-то работает, а где-то нет.
Тут сам подход неверный, если у вас есть пачка указателей на объекты, память для которых была выделена разными способами, то надо хранить и пачку соответствующих функций для их деаллокации. Проверка, лежит объект в куче или на стеке в данном случае никак не поможет; например у вас есть динамический аллокатор использующий буфер на стеке в качестве хранилища вместо кучи.
Можно написать такого рода обёртку, где будет динамически во время исполнения определяться, как был создан объект (на стеке или в куче), с помощью виртуального полиморфизма.
#include <iostream>
#include <memory>
using std::cout;
using std::endl;
using std::unique_ptr;
class PtrDeallocationWrapper {
public:
virtual ~PtrDeallocationWrapper() {}
};
template <class T>
class PtrDeallocationWrapperOnHeap
: public PtrDeallocationWrapper
{
public:
template <class... Args>
PtrDeallocationWrapperOnHeap(Args&&... args)
: ptr_(new T(std::forward<Args>(args)...))
{}
virtual ~PtrDeallocationWrapperOnHeap() {
cout << "heap deallocation" << endl;
}
private:
unique_ptr<T> ptr_;
};
template <class T>
class PtrDeallocationWrapperOnStack
: public PtrDeallocationWrapper
{
public:
PtrDeallocationWrapperOnStack(T * ptr) : ptr_(ptr) {}
virtual ~PtrDeallocationWrapperOnStack() {
cout << "stack not deallocation" << endl;
}
private:
T * ptr_;
};
template <class T, class... Args>
auto make_heap_ptr(Args&&... args)
-> unique_ptr<PtrDeallocationWrapper>
{
return std::move(unique_ptr<PtrDeallocationWrapper>(
new PtrDeallocationWrapperOnHeap<T>
(std::forward<Args>(args)...))
);
}
template <class T>
auto make_stack_ptr(T* ptr)
-> unique_ptr<PtrDeallocationWrapper>
{
return std::move(unique_ptr<PtrDeallocationWrapper>(
new PtrDeallocationWrapperOnStack<T>(ptr))
);
}
int main() {
vector<unique_ptr<PtrDeallocationWrapper> > vec;
vec.push_back(make_heap_ptr<string>("lol"));
string str1 = "kek";
vec.push_back(make_stack_ptr<string>(&str1));
vec.pop_back();
vec.pop_back();
return 0;
}
Айфон мало держит заряд, разбираемся с проблемой вместе с AppLab
Перевод документов на английский язык: Важность и ключевые аспекты
У меня аварийно завершается программа после того как я открываю диалог повторноПочему так происходить ? Может это быть из-за пустого Деструктор?...
Ясное дело, что по Стандарту вызовы malloc()/free()*, **new/delete и new[]/delete[] должны быть строго парными, иначе неопределенное поведение
Хорошим тоном в C/C++ считается использование const везде, где можно