一个对象如何知道它是在堆栈还是堆上分配的?

3

1
为什么你需要这个? - Don Roby
2
没有便携式的方法来区分它,你应该认真问自己为什么需要这个。 - PlasmaHH
1
我确信我们以前有过这个问题,但我找不到它。 - pmr
@pmr,我们在类似的情况下遇到过这个问题很多次,看起来相当普遍,但我记不得有人提出一个真正好的理由来解释为什么甚至需要这样做。 - PlasmaHH
被投票为重复 -- 严格来说,这想要区分“堆栈”与“堆”(可能意味着自动 vs 动态),而另一个则想要区分静态 vs 动态,因此存在差异。然而,对于可移植代码而言,答案是相同的。在特定实现中,可能会有工具或技术用于堆栈检查,让您检查this是否是当前线程或当前进程中任何线程的堆栈地址。 - Steve Jessop
显示剩余2条评论
2个回答

2
这个问题的简短回答是不行。
虽然有理论解决方案,例如您可以替换类或全局级别上的“new”,并跟踪所有“new”分配的指针,并将其与构造函数中的“this”指针进行比较。
struct Foo {
    Foo ()
    {
        //Check if `this` is in s_instances
    }
    void* operator new(size_t size)
    {
        void* pointer = ::new(size);
        s_instances.push_back(pointer);
        return pointer;
    }
    void operator delete (void* pointer)
    {
        //remove from s_instances and call global delete
    }
    static std::vector<void*> s_instances;
};

(这段代码无法捕获使用 new Foo[count] 分配的 Foo 对象)

不过你需要这个干嘛?


-1

没有平台无关的方法。有一些用户定义的方法。其中几个是,

(1) 您可能需要设置一个标志(作为private变量)并检查相同的标志。

struct Foo {
  const bool isHeap;
  Foo (bool heap = false) : isHeap(heap) {}
};

(2) 在重载的 new 内部进行跟踪。

struct Foo {
  static set<Foo*> heap;
  void* operator new (size_t size)
  {
    void *p = malloc(size);
    heap.insert(<p inside this set>);
  }
};

Foo :: Foo ()
{
  // check heap.find() for heap allocation
}
编辑: 以上解决方案提供了一种了解变量是自动的(通常在堆栈/数据段上)还是动态的(通常在堆段上)的方法。

1
这将无法可靠地检测堆栈分配,因为对象可能在静态存储中。 - PlasmaHH
2
请注意,(2)区分了问题中的两种情况,但通常不区分自动存储期和动态存储期。例如,如果另一个类Bar有一个Foo作为数据成员,然后将Bar分配到堆上,当然不会调用Foo::operator new,但是Foo在堆上。 - Steve Jessop
@Steve,Foo在堆上,但变量仍然是自动的(这意味着我们不需要担心它的释放和销毁)。 - iammilind
@PlasmaHH,我并没有为“static”存储提供解决方案。只是变量是否在堆上。 - iammilind
1
@iammilind:这不是“自动”的意思,“自动存储期”在3.7.2中有定义。如果提问者能够解释区别的目的,那么我们可以弄清楚这个Foo数据成员应该如何分类,但它不是“分配在堆栈上”。 - Steve Jessop
显示剩余2条评论

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