先看一段代码:

int main(void)

{

int *pI = new int;

int *pArray = new int[10];

int size = *(pArray-1);

delete pI;

delete [] pArray; // delete是如何知道pArray数组大小的?

return 0;

}

看反编译后代码,没能直接找到答案,于是在网上搜索发现这样一篇文章:《Mismatching scalar and vector new and delete》。文章中说明了内存布局大概是这样:

这个结论肯定是正确的,但是我却没能在内存中找到这个记录数组大小的地址。再看反编译代码,例子中分别new了一个对象和一个数组,例子最后使用delete[]分别删除了这两个对象。从C++角度来说,第一个delete是scalar "delete",第二个delete [] 是vector "delete"。这两种delete调用应该不一样才对,但从反编译代码看,两处调用完全相同。

; int __cdecl main()

_main proc near

var_5C= dword ptr -5Ch

var_58= dword ptr -58h

p= dword ptr -54h

var_50= dword ptr -50h

size= dword ptr -0Ch

push ebp

mov ebp, esp

sub esp, 5Ch

push ebx

push esi

push edi

push 4 ; size

call j_??2@YAPAXI@Z ; operator new(uint)

mov [ebp+var_5C], eax

mov eax, [ebp+var_5C]

mov [ebp+pI], eax

nop

push 28h ; size

call j_??2@YAPAXI@Z ; operator new(uint)

mov [ebp+var_58], eax

mov eax, [ebp+var_58]

mov [ebp+pArray], eax

nop

mov eax, [ebp+pArray]

mov ecx, [eax-4]

mov [ebp+size], ecx

nop

mov eax, [ebp+pI]

mov [ebp+p], eax

mov ecx, [ebp+p]

push ecx ; p

call j_??3@YAXPAX@Z ; operator delete(void *)

nop

mov eax, [ebp+pArray]

mov [ebp+var_50], eax

mov ecx, [ebp+var_50]

push ecx ; p

call j_??3@YAXPAX@Z ; operator delete(void *)

xor eax, eax

pop edi

pop esi

pop ebx

mov esp, ebp

pop ebp

retn

_main endp

结论:

  • 通过观察"new"调用了HeapAlloc函数,而这一函数使用可以将内存分配情况用结构体保存起来,"delete"估计就是通过这一结构体得到数组大小的。也就是说C++这一语法特点是借用了HeapAlloc等函数对Windows堆内存的管理方式实现的。

未知&待研究:

  • scalar "new" 与 vector "delete []"出现不匹配的使用时究竟会不会出现问题
  • 通过反编译验证结论。尤其是"delete []"

C++中delete[]是如何知道数组大小的的更多相关文章

  1. c++: 获取delete[]中的数组大小

    看一个小例子: 1 #include <iostream> 2   3 using namespace std; 4   5 class A { 6 public: 7     A() { ...

  2. [百度]数组A中任意两个相邻元素大小相差1,在其中查找某个数

    一.问题来源及描述 今天看了July的微博,发现了七月问题,有这个题,挺有意思的. 数组A中任意两个相邻元素大小相差1,现给定这样的数组A和目标整数t,找出t在数组A中的位置.如数组:[1,2,3,4 ...

  3. (笔试题)数组A中任意两个相邻元素大小相差1,在其中查找某个数。

    题目: 数组A中任意两个相邻元素大小相差1,现给定这样的数组A和目标整数t,找出t在数组A中的位置.如数组:[1,2,3,4,3,4,5,6,5],找到4在数组中的位置. 思路: 很明显,在数组中寻找 ...

  4. 代码实现:定义一个文件输入流,调用read(byte[] b)方法,将a.txt文件中的内容打印出来(byte数组大小限制为5)

    package com.loaderman.test; import java.io.ByteArrayOutputStream; import java.io.FileInputStream; im ...

  5. delete 和 splice 删除数组中元素的区别

    delete 和 splice 删除数组中元素的区别 ` var arr1 = ["a","b","c","d"]; d ...

  6. OpenCV中Mat与二维数组之间的转换

    ---恢复内容开始--- 在OpenCV中将Mat(二维)与二维数组相对应,即将Mat中的每个像素值赋给一个二维数组. 全部代码如下: #include <iostream> #inclu ...

  7. C语言中如何将二维数组作为函数的参数传递

    今天写程序的时候要用到二维数组作参数传给一个函数,我发现将二维数组作参数进行传递还不是想象得那么简单里,但是最后我也解决了遇到的问题,所以这篇文章主要介绍如何处理二维数组当作参数传递的情况,希望大家不 ...

  8. C/C++ 中长度为0的数组

    参考文献:http://blog.csdn.net/zhaqiwen/article/details/7904515 近日在看项目中的框架代码时,发现了了一个奇特的语法:长度为0的数组例如 uint8 ...

  9. SQL中查看数据库各表的大小

    SQL中查看数据库各表的大小 编写人:CC阿爸 2014-6-17 在日常SQL数据库的操作中,如何快速的查询数据库中各表中数据的大小. 以下有两种方法供参考: 第一种: create table # ...

随机推荐

  1. LINUX CACHE IO THREAD

    http://www.penglixun.com/tech/system/linux_cache_discovery.html http://my.oschina.net/HardySimpson/b ...

  2. Java图片处理(二)图片加水印

    图片加水印,是通过图片重叠绘制实现的.实现代码如下: public static void press(String pressImg, String pressText, String target ...

  3. java中静态的代码块,静态变量,静态方法

    简单了解一下java虚拟机--jvm几个内存区域: 方法区:在java的虚拟机中有一块专门用来存放已经加载的类信息.常量.静态变量以及方法代码的内存区域, 常量池:常量池是方法区的一部分,主要用来存放 ...

  4. UBIFS FAQ and HOWTO

    转:http://www.linux-mtd.infradead.org/faq/ubifs.html UBIFS FAQ and HOWTO Table of contents How do I e ...

  5. iOS 开发调试技巧

    对于软件开发而言,调试是必须学会的技能,重要性不言而喻.对于调试的技能,基本上是可以迁移的,也就是说你以前在其他平台上掌握的很多调试技巧,很多也是可以用在iOS开发中.不同语言.不同IDE.不同平台的 ...

  6. 数据结构【二】:简单阻塞队列BlockingQueue

    在POSIX多线程[一]:简单队列simple queue的基础上使用内部互斥锁和条件变量来控制并发以达到线程安全的目的,其主要用于 [生产者-消费者] 队列. 1.BlockingQueue初始化时 ...

  7. [xUI] ligerUI开发框架简介和搭建

    ligerUI开发者:谢略,网名daomi API:         http://api.ligerui.com/ 演示地址:  http://demo.ligerui.com/ 源码下载:  ht ...

  8. seajs 源码解读

    之前面试时老问一个问题seajs 是怎么加载js 文件的 在网上找一些资料,觉得这个写的不错就转载了,记录一下,也学习一下 seajs 源码解读 seajs 简单介绍 seajs是前端应用模块化开发的 ...

  9. 【高德地图开发4】---增加覆盖物setMapTextZIndex

    高德地图 Android SDK 允许用户将添加的线.面等覆盖物设置在地图底图文字的上方或下方. 具体实现是使 用 AMap 类的 setMapTextZIndex() 方法来设置地图底图文字的z轴指 ...

  10. 【Shell脚本学习4】几种常见的Shell

    上面提到过,Shell是一种脚本语言,那么,就必须有解释器来执行这些脚本. Unix/Linux上常见的Shell脚本解释器有bash.sh.csh.ksh等,习惯上把它们称作一种Shell.我们常说 ...