一种异常解析-HeapValidate异常-程序员宅基地

技术标签: C/C++  

(Owed by: 春夜喜雨 http://blog.csdn.net/chunyexiyu)

参考文档:

http://blog.csdn.net/hgy413/article/details/6716397

http://blog.csdn.net/lbhli/article/details/6797145

前注:

删除类的编译翻译,例如delete pItem; 会翻译成

1. pItem::~析构函数();       // 调析构

2. operator delete(pItem); // 调类对象所占内存清理(大小sizeof(类))

如果pItem的类的析构为虚函数时,翻译成 

1. 调用虚函数表中的析构函数,一层一层调用析构函数

2. 重设删除地址 (猜测,基于上一步指向虚函数的实际类型,对指针重设:类似 CChlid继承自CItem, CChild* pChild = (CChild*)pItem,从而指针与CItem指针偏移差考虑进来) 

3. operator delete(删除地址);

1. 父类无虚构函数,子类有虚构函数,使用父类delete时崩溃

class IBase
{
public:
};

class CItem1 : public IBase
{
public:
    virtual void A(){}
};
int main()
{
   IBase* pBase = CItem1();
   delete pBase;
}

添加调测代码,查输出的话,可以看到父类指向的地址偏移了四位(虚函数表的空间)

输出:

pItem=0x5d0610, sizeof(*pItem)=4
pBase=0x5d0614, sizeof(*pBase)=1

#define ViewPointerAddress(pVal) ViewPointerAddressFunc(#pVal, pVal)
template <typename T>
void ViewPointerAddressFunc(char* pCharName, T* pPointer)
{
    char sLog[256];
    sprintf_s(sLog, "%s=0x%x, sizeof(*%s)=%d\n", pCharName, pPointer, pCharName, sizeof(*pPointer));
    printf(sLog);
    OutputDebugStringA(sLog);
}
...
    ViewPointerAddress(pItem);
    ViewPointerAddress(pBase);
...

报错在HeapValide异常这一块,为什么会报错呢:

进一步按照debug的方法,添加调试代码,定位可以看到:

    _CrtMemBlockHeader *pBaseHdr = pHdr(pBase);
    _CrtMemBlockHeader *pItemHdr = pHdr(pItem);
    HeapValidate(GetProcessHeap(), 0, pHdr(pItem));
    HeapValidate(GetProcessHeap(), 0, pHdr(pBase));

报错在 HeapValidate(GetProcessHeap(), 0, pHdr(pBase)) 这句话上,从结构上看:pBaseHdr中是有些异常的

分析:

每个内存分配前面都放有一个 _CrtMemBlockHeader 结构,但像上面的情况,由于pBase的地址偏移了4位,导致获取它前面的 _CrtMemBlockHeader 存在异常

所以HeapValidate鉴权失败,崩溃退出

2. 多重继承时的问题:

多重继承虚函数时,也有类似的问题,例如:

class A{ public: virtual void f1()=0;};

class B{ public: virtual void f2()=0;};

class C : public A, public B {}

C* pC = new C();

B* pB = pC;

delete pB;

此时如果新建C对象,使用B指向他的时候,地址会偏移4字节,delete使用B指针的话导致异常;使用A指针的话,由于编译器把他放在前面,它的问题不大,不会崩溃。

pItem=0x4a02f0, sizeof(*pItem)=8
pBaseA=0x4a02f0, sizeof(*pBaseA)=4
pBaseB=0x4a02f4, sizeof(*pBaseB)=4

其实对于多重继承,有没有虚函数,使用非第一个继承类删除都会有问题,例如:

class A{ public: int a;};

class B{ public: int b;};

class C : public A, public B {int c;}

C* pC = new C();

B* pB = pC;

delete pB;

查看指针的话,会看到内存分布:A|B|c-内部变量

(转成A的时候,删除没有问题;转成B删除就会有问题)

(Owed by: 春夜喜雨 http://blog.csdn.net/chunyexiyu)




版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/chunyexiyu/article/details/49358199

智能推荐

基于Spark的机器学习实践 (二) - 初识MLlib_mlib基于spark core-程序员宅基地

文章浏览阅读2k次。1 MLlib概述1.1 MLlib 介绍◆ 是基于Spark core的机器学习库,具有Spark的优点◆ 底层计算经过优化,比常规编码效率往往要高◆ 实现了多种机器学习算法,可以进行模型训练及预测1.2 Spark MLlib实现的算法◆ 逻辑回归 朴素贝叶斯 线性回归 SVM 决策树 LDA 矩阵分解1.3 Spark MLlib官方介绍1.3.1 搜索官方文档1.3..._mlib基于spark core

《剑指offer》——二叉树的下一个结点-程序员宅基地

文章浏览阅读401次。题目: 给定一个二叉树和其中的一个结点,请找出中序遍历顺序的下一个结点并且返回。注意,树中的结点不仅包含左右子结点,同时包含指向父结点的指针。思路: 分析二叉树的下一个节点,一共有以下情况: 1.二叉树为空,则返回空; 2.节点右孩子存在,则设置一个指针从该节点的右孩子出发,一直沿着指向左子结点的指针找到的叶子节点即为下一个节点; 3.节点不是根节点。如果该节点是其父节点的左孩子,则返

数字反转的列表实现方法(python)_python在函数内,将数字num转换为其相反顺序的数字列表。-程序员宅基地

文章浏览阅读1.3k次。做题心得_python在函数内,将数字num转换为其相反顺序的数字列表。

Java 之 FileReader FileInputStream InputStreamReader BufferedReader 作用与区-程序员宅基地

文章浏览阅读57次。ava.io下面有两个抽象类:InputStream和ReaderInputStream是表示字节输入流的所有类的超类Reader是用于读取字符流的抽象类InputStream提供的是字节流的读取,而非文本读取,这是和Reader类的根本区别。即用Reader读取出来的是char数组或者String,使用InputStream读取出来的是byte数组。弄清了两个超类的根本区别,再来看他们底下..._java bufferreader inputstream

linux 安装语言模型工具KenLm_kenlm依赖有哪些-程序员宅基地

文章浏览阅读450次。1、安装相关依赖包cmake、boost和bzip2,其中后两个需要root权限2、安装kenlmwget http://kheafield.com/code/kenlm.tar.gztar -zxvf kenlm.tar.gzcd kenlmmkdir buildcd buildcmake …make注:到make这一步时报错,需要修改C++编译器。在CMakeLists.txt头部添加以下命令:SET(CMAKE_CXX_FLAGS “${CMAKE_CXX_FLAGS} _kenlm依赖有哪些

react native搭建私有热更新服务器_react native 热更新 私有-程序员宅基地

文章浏览阅读2.8k次。公司要求要有自己的私有热更新服务器,本人表示不擅长后台,只好去网上找相关的文章,与技术博客:本文简历在已经成功运行 微软 codepush热更新,并且了解codepush 相关指令的基础上。 参考文章-iOS参考文章-android简介code-push-server是一个开源项目,基于 nodejs + mysql 搭建自己的热更新服务器环境macOS Sierr_react native 热更新 私有

随便推点

python不同曲线设置标签_python 绘制拟合曲线并加指定点标识的实现 Python怎么实现非线性的拟合...-程序员宅基地

文章浏览阅读642次。Python 怎么用曲线拟合数据我有两组数据: y = [41.417, 49.077, 26.683, 42.137, 37.31, 10.022, Python中利用guiqwt进行曲线数据拟合。怎么用Python将图像边界用最小二乘法拟合成曲线怎么用matplotlib在同一个图上画离散点及其拟合直线也许是怕再伤对方一次,所以分手时,一个没有挽留,另一个也没回头。python如何分享一条拟合..._不同曲线标签 python

转义JavaScript特殊字符-程序员宅基地

文章浏览阅读80次。JavaScriptUtils.javaScriptEscape("%admin' or '1=1") //转义JavaScript特殊字符 转载于:https://www.cnblogs.com/xianhenyuan/..._"javascriptutils.javascriptescape(\"%admin' or '1=1\")"

java 更新list内的元素_list更新元素-程序员宅基地

文章浏览阅读1.5w次。/*** 更新list内的元素。* @param objlist* @param oldObj 旧对象* @param newObj 要更新的对象* @return*/public List updateElement(List objlist,Object oldObj,Object newObj){int position=objlist.indexOf(old_list更新元素

wamp2.1配置虚拟主机-程序员宅基地

文章浏览阅读71次。修改配置文件httpd.conf,并去掉#Include conf/extra/httpd-vhosts.conf前面的#修改apache/conf/extra/httpd-vhosts.conf<VirtualHost*:80>DocumentRoot"D:/wamp/www"ServerNamelocalhost<D..._wamp 2.2 虚拟映射

webstorm nodejs ESLint 简单配置-程序员宅基地

文章浏览阅读179次。ESLint 简介 官网http://eslint.org/ 在团队协作中,为避免低级 Bug、产出风格统一的代码,会预先制定编码规范。使用 Lint 工具和代码风格检测工具,则可以辅助编码规范执行,有效控制代码质量。 在以前的项目中,我们选择 JSHint 和 JSCS 结合使用,W..._webstorm 开启js-lint

linux下运行python与windows速度差别,Linux和Windows之间的numpy性能差异-程序员宅基地

文章浏览阅读663次。I am trying to run sklearn.decomposition.TruncatedSVD() on 2 different computers and understand the performance differences.computer 1 (Windows 7, physical computer)OS Name Microsoft Windows 7 Profess..._python 并行linux比windows慢