zoukankan      html  css  js  c++  java
  • C++中delete[]是如何知道数组大小的

    先看一段代码:

    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

    pArray= dword ptr -8

    pI= dword ptr -4

     

    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)

    add esp, 4

    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)

    add esp, 4

    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 *)

    add esp, 4

    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 *)

    add esp, 4

    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 []"

  • 相关阅读:
    离线修改注册表
    在Spring3中,配置DataSource的方法有6种。
    windows设置java环境变量
    三种配置linux环境变量的方法(以java为例)
    java call sap
    Tomcat 解决The code of method _jspService(HttpServletRequest, HttpServletResponse) is exceeding the 65535 bytes limit
    window上安装pymysql
    Python中的str与bytes之间的转换的三种方法
    安装sqlite3.8的方法
    os.walk的用法
  • 原文地址:https://www.cnblogs.com/cartler/p/3400610.html
Copyright © 2011-2022 走看看