请问怎么判定一个指针指向的对象是栈内存还是堆内存

请教如何判定一个指针指向的对象是栈内存还是堆内存
我想请教下各位大侠, 如何判定一个指针指向的对象是栈内存还是堆内存(new ,malloc 分配的),例如函数参数是个指针,如何知道其所指对象是不是new,malloc分配的内存。
还有如果该对象是栈内存,却调用delete操作,会有什么具体的后果?
多谢多谢!

我就能给这么多分了:)

------解决方案--------------------
呵呵
那如果对象是栈内存,却调用delete操作,会有什么具体的后果?
会提示改指针指向的不是一个有效的堆内存块,调用delete时,在真正释放堆内存前
会有很多检查的(一些检查函数的调用),你可以跟踪一下底层的汇编代码看看

第一个问题应该没有通用的方法吧,不过如果针对于“当前当时”的机器,你可以看看你
第一次分配的栈内存的起始地址是多少A1,第一次动态分配的内存的起始地址是多少A2。。。。。。
默认情况下栈的大小是1M(好像是),然后比较一下
不过这样做没有意思

你可能想在函数内释放外面传进来的指向动态分配内存的指针,建议不要这样做,
在函数外面分配的就在函数外面释放,函数像是一种接口,别人调用你的函数时,
根本不清楚也没有必要知道函数的实现细节,如果你在函数里面释放了动态分配的内存,
知道函数实现细节的还好,万一不知道的,他在调用完函数后又释放一次动态分配的内存
程序肯定会出错的!!
------解决方案--------------------
对于单线程,可以判断指针指的内存是否在用户栈中
多线程不好办

C/C++ code
//测试指针所指内存在栈中,还是堆中

#include <iostream>
using namespace std;

void* stack_bottom=NULL;    
void test();

void ptr_in_stack(void* ptr)
{    
    //此函数被调用时,一定是在栈顶的

    void* stack_top=&stack_top;//获取栈顶位置
    if( stack_bottom>ptr && stack_top<ptr)//比较地址范围
    {
        cout<<"指针"<<ptr<<"在栈中"<<endl;
    }
    else
    {
        cout<<"指针"<<ptr<<"不在栈中"<<endl;
    }
}

void test()
{
    int i=0; 
    ptr_in_stack(&i);

    int array[10000];
    ptr_in_stack(&array[10]);

    int *p = new int;
    ptr_in_stack(p);
}

int main()
{
    int i;
    stack_bottom = &i;  //记录栈底位置,不是很精确
    test();
    return 0;
}

------解决方案--------------------
Move effective C++ 里面专门有讲过这个问题,基本上没有可移植的方法来判断一个对象到底实在栈上还是在堆上。

不过书上也提出了一个解决办法,那就是重载operator new 和 operator delete函数,在operator new中将所有分配的
得到的指针放入一个链表,当调用operator delete时查看需要delete的指针是否存在与链表中,如果不在则表示当前delete
的指针不是有operator new分配的。

C/C++ code

//.h
   class HeapTracked { // 混合类; 跟踪
  public:           // 从operator new返回的ptr

   class MissingAddress{}; // 异常类,见下面代码

   virtual ~HeapTracked() = 0;

   static void *operator new(size_t size);//重载operator new 和operator delete
   static void operator delete(void *ptr);

   bool isOnHeap() const;

  private:
   typedef const void* RawAddress;
   static list<RawAddress> addresses;
  };

//.cpp
// mandatory definition of static class member
  list<RawAddress> HeapTracked::addresses;

  // HeapTracked的析构函数是纯虚函数,使得该类变为抽象类。
  // (参见Effective C++条款14). 然而析构函数必须被定义,
  //所以我们做了一个空定义。
  HeapTracked::~HeapTracked() {}

  void * HeapTracked::operator new(size_t size)
  {
   void *memPtr = ::operator new(size); // 获得内存
   addresses.push_front(memPtr);       // 把地址放到list的前端
   return memPtr;
  }

  void HeapTracked::operator delete(void *ptr)
  {
   //得到一个 "iterator",用来识别list元素包含的ptr;
   //有关细节参见条款35
   list<RawAddress>::iterator it =
    find(addresses.begin(), addresses.end(), ptr);

   if (it != addresses.end()) { // 如果发现一个元素
    addresses.erase(it);      // 则删除该元素
     ::operator delete(ptr); // 释放内存
   }
   else { // 否则
    throw MissingAddress(); // ptr就不是用operator new
   }                      // 分配的,所以抛出一个异常
  } 

  bool HeapTracked::isOnHeap() const
  {
   // 得到一个指针,指向*this占据的内存空间的起始处,
   // 有关细节参见下面的讨论
   const void *rawAddress = dynamic_cast<const void*>(this);

   // 在operator new返回的地址list中查到指针
   list<RawAddress>::iterator it =
    find(addresses.begin(), addresses.end(), rawAddress);

   return it != addresses.end(); // 返回it是否被找到
  }

------解决方案--------------------
理论上说,特定在win32平台上,还是有办法检验指针是否是分配在堆上的。
因为malloc内部是调用HeapAlloc的,因此只要取得相应的指针的handle就可以直接调用win32 API的HeapValidate函数来判断该指针是否是在堆上。
至于如何从指针取得handle的方法,我没有在库函数中找到,这个可能是跟库相关的。