Можно ли динамически определить, как был создан объект - на куче или в стеке?

158
07 октября 2018, 13:30

Например проверять объект при очищении контейнера:

#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;
}

Есть ли стандартные механизмы определения, каким способом создан объект?

Answer 1

Определить , что адрес в стеке можно с помощью проверки адреса:

bool  isInStack(void * x) {
  volatile  bool  stacktop  ;
  return  x > ( & stacktop ) ; }

Но проблема с другими адресами: глобальных переменных. У них адреса не в стеке , а в куче. И определить, что нужно удалять или нельзя придётся вручную, задавая вектор структуры с флагом , что нужно удалить. Данный способ определять место информации , что оно стеке очень ИНДИВИДУАЛЬНЫЙ. Это называется ХАКИНГ. Где-то работает, а где-то нет.

Answer 2

Тут сам подход неверный, если у вас есть пачка указателей на объекты, память для которых была выделена разными способами, то надо хранить и пачку соответствующих функций для их деаллокации. Проверка, лежит объект в куче или на стеке в данном случае никак не поможет; например у вас есть динамический аллокатор использующий буфер на стеке в качестве хранилища вместо кучи.

Answer 3

Можно написать такого рода обёртку, где будет динамически во время исполнения определяться, как был создан объект (на стеке или в куче), с помощью виртуального полиморфизма.

#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;
}
READ ALSO
Как правильно создавать Dialog?

Как правильно создавать Dialog?

У меня аварийно завершается программа после того как я открываю диалог повторноПочему так происходить ? Может это быть из-за пустого Деструктор?...

169
C++ delete и delete[]

C++ delete и delete[]

Ясное дело, что по Стандарту вызовы malloc()/free()*, **new/delete и new[]/delete[] должны быть строго парными, иначе неопределенное поведение

149
В чем смысл использования auto?

В чем смысл использования auto?

В сети нашел статьи, например такиую: статья

150
C++, избавление объекта от квалификатора const

C++, избавление объекта от квалификатора const

Хорошим тоном в C/C++ считается использование const везде, где можно

165