如何知道对象的创建是在堆上还是栈上?

4

我们希望开发低延迟系统,应用程序中堆分配的成本较高。但在某种程度上允许在堆上创建对象。因此,我们希望知道对象是否在堆上创建...?

以下方法是确定对象是否在堆内存上创建的正确方式吗..?

将会有一个通用类,在其中重载new和delete运算符以维护堆分配的指针...

#include <iostream>
#include <set>

using namespace std;

class MemStat              //base class
{
    typedef set<MemStat*> POINTERS; 
    static POINTERS m_ptrlist;
public:
    void* operator new (size_t size)
    {
        MemStat* ptr = ::new MemStat;
        m_ptrlist.insert(ptr);
        return ptr;
    }
    void operator delete(void* dptr)
    {
        MemStat* ptr = static_cast<MemStat*>(dptr);
        m_ptrlist.erase(ptr);
        ::delete ptr;
    }
    // void* operator new[] (size_t sz);
    // void operator delete[] (void*);

    bool is_on_heap() { m_ptrlist.find(this) != m_ptrlist.end(); }

protected:             // ctor & dtor are protected for restrictions
    MemStat() { }
    virtual ~MemStat() { }
    MemStat(const MemStat&) { } 
    const MemStat& operator=(const MemStat& ) { return *this; }
};
MemStat::POINTERS MemStat::m_ptrlist;

对于我们需要检查堆创建的最终用户类将从MemStat类派生,使用new和delete运算符调用基类对象实例化。

class MyClass : public MemStat   //end user class
{
};

int main()
{
    MyClass* myptr = new MyClass;
    MyClass obj;

    cout << myptr->is_on_heap() << endl;    //results into yes
    cout << obj.is_on_heap() << endl;       //reults into no

    delete myptr;
}
1个回答

7
请注意,一旦一个MyClass对象是另一个对象的子对象(继承或包含),并且该对象可能或可能不会动态分配,那么您的方案将彻底失败。(我知道的用于防止动态分配的技巧在这个问题上也会失败。)
因此,您所做的只是进一步减慢堆分配速度而没有获得太多好处。除了极少数情况外,对象的分配是您类的用户决定的事情。如果他们认为需要动态分配一个对象,那么您有什么理由反对呢?

任何数量的分配器调试方案也会导致指针不完全匹配。因此,set 不合适。但是,通过存储每个分配的大小并在搜索中使用该信息,应该可以找出 this 是否落在任何已分配的区域内。根据代码需要多么可移植,可能可以使用底层分配器的堆行走 API,而不是冗余地存储块信息。 - Ben Voigt

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接