如何判断一个C++对象是否在堆栈上

昨天有人在QQ群里问到如何判断一个C++对象是否在堆栈上, 我在网上搜索了下, 搜到这个么一个CSDN的帖子 http://topic.csdn.net/t/20060124/10/4532966.html ,可惜它也没有给出一个合适的答案。

要解答这个问题,其实就是要知道的堆栈的起始地址, 而我们知道堆栈其实就是一段有相同属性的内存页面,而Windows也是有API让我们查询虚拟内存的页面分配情况的。所有我们可以通过VirtualQuery这个API来获取堆栈的起始地址,然后就可以得到答案了。

BOOL IsObjectOnStack(LPVOID pObject)
{
    INT nStackValue(0);

    MEMORY_BASIC_INFORMATION mi = {0};
    DWORD dwRet = VirtualQuery(&nStackValue, &mi,  sizeof(mi));

     if(dwRet > 0)
    {
         return pObject >= mi.BaseAddress 
            && (DWORD)pObject < (DWORD)mi.BaseAddress + mi.RegionSize;
    }

     return FALSE;
}

int g_value = 10;

int main( int argc,  char* argv[])
{
     int nStackValue = 1;
     int* p =  new  int(10);
    
    BOOL bStackValue = IsObjectOnStack(&g_value);   // false
        bStackValue = IsObjectOnStack(&nStackValue);  // true
        bStackValue = IsObjectOnStack(p);  // false

    system("pause");

     return 0;
}

当然,我们知道每个线程都有自己的堆栈,所以上面的方法针对线程1查询线程1的堆栈对象是可行的,线程2查询线程2的堆栈对象页是可行的,但是线程1查询线程2的堆栈对象就不行了。所以多线程情况下,我们可以统计出所有的线程堆栈起始地址,然后统一判断。当然随着线程的建立和销毁,堆栈本身也是在不断变化的。

我想了下,不知道判断对象是否在堆栈上在我们实际编程中有什么用,谁知道的话麻烦提示下。

以上代码在Windows下测试通过,如果有不正确的地方,欢迎指正。
posted on 2012-05-12 10:57 Richard Wei 阅读(1626) 评论(9)   编辑  收藏 引用 所属分类: C++

FeedBack:
#  re: 如何判断一个C++对象是否在堆栈上
2012-05-12 12:32 | 溪流
学习了   回复   更多评论
  
#  re: 如何判断一个C++对象是否在堆栈上
2012-05-12 13:57 | learner
搂主,怎么判断是不是堆对象?   回复   更多评论
  
#  re: 如何判断一个C++对象是否在堆栈上
#  re: 如何判断一个C++对象是否在堆栈上[未登录]
2012-05-12 21:06 | jk
不需要windows api也可以做到   回复   更多评论
  
#  re: 如何判断一个C++对象是否在堆栈上
2012-05-12 22:33 | Duwen
楼主您好,因为这个错误不小,所以我还是觉得应该指出,只为共同学习
"我们知道每个线程都有自己的堆栈,所以上面的方法针对线程1查询线程1的堆栈对象是可行的,线程2查询线程2的堆栈对象页是可行的,但是线程1查询线程2的堆栈对象就不行了"
这句话错了,系统在在为每个进程初始化时创建一个默认堆,它是全局的,该进程中的所有线程共用这个全局堆,而系统会为每个线程创建一个栈,也就是说,如果没有自己手动创建堆(HeapCreate),那么一个进程只有一个堆,而栈是线程相关的.我想楼主本意是想说栈,而"堆栈"这个词用的多了,就疏忽了   回复   更多评论
  
#  re: 如何判断一个C++对象是否在堆栈上
2012-05-12 22:48 | Richard Wei
@Duwen
多谢指正,希望共同进步。

恩,可能表达不是很清楚,我上面说的堆栈其实指的就是栈(Stack)。

至于堆(Heap), 每个进程除了默认堆,还有其他的, 比如C/C++ CRT就会创建自己的堆,我们每次new对象,默认都是在该堆里进行的。所以如果我们写程序时每个模块(DLL)用静态方式链接CRT,在DLL内new对象时都会在DLL自己的CRT堆上创建对象。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值