zoukankan      html  css  js  c++  java
  • 从一个笔误引起的思考

    以下测试环境均在Visual C++ 2005,WIN7 SP1 64位系统之上。

    几天前组内一个同事做技术分享,其中谈到一个问题,如果new出一个对象但是delete的时候,如果写成delete[]效果会如何。其中有同事在实际测试中发现如果是debug版本会抛异常,但是Release会反复执行该对象的析构函数。debug版本拋异常很容易理解,本来这么写就不对的,但是Release版本为什么会不断执行析构函数呢?如果是这样那又会执行多少次才会结束?笔者做了一下简单分析找到了其中原因,在解决这个问题之前我们先看看下面的代码和内存布局:

    #include "stdafx.h"
    #include <windows.h>
    
    DWORDLONG g_dwTestCount = 0;
    class CTest
    {
    public:
    	~CTest()
    	{
             ++g_dwTestCount;
    	}
    
    	int i;
    };
    
    int _tmain(int argc, _TCHAR* argv[])
    {
    	CTest *pTestAry = new CTest[10];
    	delete[] pTestAry;
    
    	CTest *pTest = new CTest;
    	printf("%p
    ",pTest);
    	delete [] pTest;
    
    	printf("%x",g_dwTestCount);
    	getchar();
    	return 0;
    }
    

    当程序执行过CTest *pTestAry = new CTest[10];,查看pTestAry内存发现数据如下:

    前后cd部分就是系统分给用户的可用内存,其中红色标记的部分代表后面元素的个数,而delete[]的时候首先会读取这里的值,很明显的可以看出来在实际分配的堆内存中,往前4个自己代表分配元素个数;但是对new出来的单个对象却没有这个标识。但是如果说修改掉这个值会怎么样呢?通过实际测试,在delete之前直接把内存中的值修改掉,结果发现改成多少析构函数就执行多少次。

    写到这里相信读者已经可以想到Release的情况,因为Release版本的堆结构和Debug版本有一定差别,在实际调试中并没有前后4个fd的情况。而之前的数字也并不固定,所以执行析构函数的次数也并非固定。

    附图:笔者用windbg截图出Release版本的执行结果和内存数据:

  • 相关阅读:
    Mecanim分析
    Mecanim 动作复用示例
    Unity3D FPS帧数修改
    Unity游戏暂停之Update与FixedUpdate区别
    我对程序开发流程的理解
    Zygote进程【1】——Zygote的诞生
    Android之SDK、NDK、JNI和so文件
    Android的4种文件类型Java,class,dex,apk
    android系统架构解析
    Android ART运行时与Dalvik虚拟机
  • 原文地址:https://www.cnblogs.com/mod109/p/3947370.html
Copyright © 2011-2022 走看看