如何判断一个C++对象是否在堆上(通过GetProcessHeaps取得所有堆,然后与对象地址比较即可),附许多精彩评论

在帖子如何判断一个C++对象是否在堆栈上 中, 又有人提出如何判断一个C++对象是否在堆上。

其实我们可以参照那个帖子的方法类似实现,我们知道堆就是Heap,在windows上我们可以通过GetProcessHeaps来得到所有的堆句柄,而我们这里只要知道Windows上的Heap Handle,其实就是堆的起始地址,就可以写如下代码了。

#include <iostream>
#include <windows.h>

using namespace std;

BOOL IsObjectOnHeap(LPVOID pObject)
{
    BOOL bRet(FALSE);
    DWORD dwHeaps = GetProcessHeaps(0, NULL);
    LPHANDLE pHeaps = new HANDLE[dwHeaps];
    if(pHeaps != NULL)
    {
        MEMORY_BASIC_INFORMATION mi = {0};
        GetProcessHeaps(dwHeaps, pHeaps);

for(INT i=0; i<dwHeaps; ++i)
        {
            VirtualQuery((LPVOID)pHeaps[i], &mi, sizeof(mi));
            
            if(pObject >= mi.BaseAddress 
                && (DWORD)pObject < (DWORD)mi.BaseAddress + mi.RegionSize)
            {
                bRet = TRUE;
                break;
            }
        }
    }
    delete []pHeaps;

return bRet;
}

int g_value = 10;

int main(int argc, char* argv[])
{
    int nStackValue = 1;
    int* pNew = new int(10);
    int* pNewArray = new int[100];

static int static_value = 0;
    
    cout << "g_value:" << IsObjectOnHeap(&g_value) << endl;  //false
    cout << "nStackValue:" << IsObjectOnHeap(&nStackValue) << endl;   //false
    cout << "static_value:" << IsObjectOnHeap(&static_value) << endl;    //false
    cout << "pNew:" << IsObjectOnHeap(pNew) << endl;        //true
    cout << "pNewArray:" << IsObjectOnHeap(pNewArray) << endl;    //true

system("pause");
    return 0;
}

以上代码在Windows下测试通过(也只能在Windows上跑),如果有不正确的地方,欢迎指正。

注: 上面关于对象是否在堆上的判断应该是不对,因为堆内存不是连续内存,内部是通过类似链表的结构来实现的,<<软件调试>>里有相关介绍,也可以通过WinDbg的 !address 命令查看内存分布

http://www.cppblog.com/weiym/archive/2012/05/12/174657.html

其实判断一个对象是在堆上还是在栈上根本不必这么复杂,因为,系统默认栈地址是固定的,栈空间最多长到1MB,若超过1MB会引发栈耗尽异常,所以只需判断是否在栈上,就只是看看有没有在这个地址区间内

时间: 2024-12-29 12:27:49

如何判断一个C++对象是否在堆上(通过GetProcessHeaps取得所有堆,然后与对象地址比较即可),附许多精彩评论的相关文章

如何判断一个C++对象是否在堆栈上(通过VirtualQuery这个API来获取堆栈的起始地址,然后就可以得到答案了),附许多精彩评论

昨天有人在QQ群里问到如何判断一个C++对象是否在堆栈上, 我在网上搜索了下, 搜到这个么一个CSDN的帖子http://topic.csdn.net/t/20060124/10/4532966.html ,可惜它也没有给出一个合适的答案. 要解答这个问题,其实就是要知道的堆栈的起始地址, 而我们知道堆栈其实就是一段有相同属性的内存页面,而Windows也是有API让我们查询虚拟内存的页面分配情况的.所有我们可以通过VirtualQuery这个API来获取堆栈的起始地址,然后就可以得到答案了.

iOS判断一个View是否显示在屏幕上

有时候做UI的时候,比如需要判断scrollView中一个btn是否显示在屏幕上,可以用以下代码: #pragma mark - 返回一个View所在的位置x,y,是否在rect坐标里面 - (BOOL)isInScreenView:(UIView *)inView withRect:(CGRect)rect{ return CGRectIntersectsRect(inView.frame, rect); } #pragma mark - 返回判断screenRect所在的位置x,y,是否在r

判断一个值是否在数组里,可以检测数字,字符串,json对象

Array.prototype.indexOf = function (val) {//判断数组是否存在某个值,如果存在返回该值对应的索引,否则返回-1 for (var i = 0; i < this.length; i++) { if(typeof val === 'object' && typeof this[i]==='object'){ var str1 = JSON.stringify(val); var str2 = JSON.stringify(this[i]); i

C++只在栈或堆上实例化对象

C++如何让类对象只能在堆(栈)上分配空间 一般情况下写一个类都是可以采用new在堆上分配空间,或直接采用 类名+对象名 的方式在栈上分配空间.但有时候,如果想让一个类只能在栈上或者堆上分配空间,又该怎么实现呢? 下面分别来介绍如何定义只能在栈上或堆上实例化的类. 注:1.静态实例化对象 如 A a;的步骤为:先由编译器为对象在栈空间分配内存,移动栈顶指针,挪出适当的空间,然后在这个空间上调用构造函数形成一个对象,在对象使用完之后,调用析构函数回收内存,栈顶指针减一.2.动态实例化对象:new操

怎样判断一个点是否落在View内,判断是否手指移动到一个View中

在3.0时代之前,要判断一个点是否落在 View 上只需要两步:第一步:得到 View 的 Rect,第二步:判断点是否再这个 Rect 内. 但从 Android 3.0 开始这样的简单日子就结束了. 原因在于,Google 为 Android 3.0 提供了一套新的动画框架:Property Animation .View/ViewGroup为此获得了强大的动画能力,但代价是View/ViewGroup的实现比以前更复杂了.3.0 前的 View/ViewGroup 在被画到画布前只会经过一

JavaScript判断一个变量是对象还是数组

typeof都返回object 在JavaScript中所有数据类型严格意义上都是对象,但实际使用中我们还是有类型之分,如果要判断一个变量是数组还是对象使用typeof搞不定,因为它全都返回object 1 2 3 4 5 6 var o = { 'name':'lee' }; var a = ['reg','blue']; document.write( ' o typeof is ' + typeof o); document.write( ' <br />'); document.wri

如何定义一个只能在堆上(栈上)生成对象的类?

在C++中,类的对象建立分为两种,一种是静态建立,如A a:另一种是动态建立,如A* ptr=new A:这两种方式是有区别的. 静态建立一个类对象,是由编译器为对象在栈空间中分配内存,是通过直接移动栈顶指针,挪出适当的空间,然后在这片内存空间上调用构造函数形成一个栈对象.使用这种方法,直接调用类的构造函数. 动态建立类对象,是使用new运算符将对象建立在堆空间中.这个过程分为两步,第一步是执行operator new()函数,在堆空间中搜索合适的内存并进行分配:第二步是调用构造函数构造对象,初

判断一个序列是不是堆

解决这个问题前先来看一个题目,如下:以下序列不是堆的是()A.(100,85,98,77,80,60,82,40,20,10,66)B.(100,98,85,82,80,77,66,60,40,20,10)C.(10,20,40,60,66,77,80,82,85,98,100)D.(100,85,40,77,80,60,66,98,82,10,20)要解决这个问题就要知道关于判断堆的知识:堆分为最大堆和最小堆,如果把一个数列画为一颗二叉树的话,那么根结点是i,左子树是2i,右子树是2i+1.对

struct对象可能分配在托管堆上吗

struct对象可能被分配在托管堆上吗? --会的. 比如当对struct装箱的时候,就会被分配在托管堆上. 比如,让一个struct实现一个接口. public interface IReport { string Name { get; } } public struct Score : IReport { public string Name { get { return "80分来自struct"; } } } 再来一个类负责打印接口属性值的类和方法. public class