Is delete[] equal to delete?

前端 未结 6 1588
-上瘾入骨i
-上瘾入骨i 2020-11-22 01:05
IP_ADAPTER_INFO *ptr=new IP_ADAPTER_INFO[100];

if I free using

delete ptr;

will it lead to memory leak, if not t

相关标签:
6条回答
  • 2020-11-22 01:33

    Whether this leads to a memory leak, wipes your hard disk, gets you pregnant, makes nasty Nasal Demons chasing you around your apartment, or lets everything work fine with no apparent problems, is undefined. It might be this way with one compiler, and change with another, change with a new compiler version, with each new compilation, with the moon phases, your mood, or depending on the number of neutrinos that passed through the processor on the last sunny afternoon. Or it might not.

    All that, and an infinite number of other possibilities are put into one term: Undefined behavior:

    Just stay away from it.

    0 讨论(0)
  • 2020-11-22 01:39

    Just an illustration of some "undefined" behaviors on certain OSes and compilers. Hope it could be helpful for people to debug their code.

    Test 1

    #include <iostream>
    using namespace std;
    int main()
    {
      int *p = new int[5];
      cout << "pass" << endl;
      delete p;
      return 0;
    }
    

    Test 2

    #include <iostream>
    using namespace std;
    int main()
    {
      int *p = new int;
      cout << "pass" << endl;
      delete[] p;
      return 0;
    }
    

    Test 3

    #include <iostream>
    using namespace std;
    struct C {
      C() { cout << "construct" << endl; }
      ~C() { cout << "destroy" << endl; }
    };
    
    int main()
    {
      C *p = new C[5];
      cout << "pass" << endl;
      delete p;
      return 0;
    }
    

    Test 4

    #include <iostream>
    using namespace std;
    struct C {
      C() { cout << "construct" << endl; }
      ~C() { cout << "destroy" << endl; }
    };
    
    int main()
    {
      C *p = new C;
      cout << "pass" << endl;
      delete[] p;
      return 0;
    }
    
    • Windows 7 x86, msvc 2010. Compile with default options, i.e. exception handler is enabled.

    Test 1

    pass
    

    Test 2

    pass
    

    Test 3

    construct
    construct
    construct
    construct
    construct
    pass
    destroy
    # Then, pop up crash msg
    

    Test 4

    construct
    pass
    destroy
    destroy
    destroy
    destroy
    destroy
    destroy
    destroy
    ... # It never stop until CTRL+C
    
    • Mac OS X 10.8.5, llvm-gcc 4.2 or gcc-4.8 generate the same output

    Test 1

    pass
    

    Test 2

    pass
    

    Test 3

    construct
    construct
    construct
    construct
    construct
    pass
    destroy
    a.out(71111) malloc: *** error for object 0x7f99c94000e8: pointer being freed was not allocated
    *** set a breakpoint in malloc_error_break to debug
    zsh: abort      ./a.out
    

    Test 4

    construct
    pass
    a.out(71035) malloc: *** error for object 0x7f83c14000d8: pointer being freed was not allocated
    *** set a breakpoint in malloc_error_break to debug
    zsh: abort      ./a.out
    
    • Ubuntu 12.04, AMD64, gcc 4.7

    Test 1

    pass
    

    Test 2

    pass
    

    Test 3

    construct
    construct
    construct
    construct
    construct
    *** glibc detected *** ./a.out: munmap_chunk(): invalid pointer: 0x0000000001f10018 ***
    ======= Backtrace: =========
    /lib/x86_64-linux-gnu/libc.so.6(+0x7eb96)[0x7fe81d878b96]
    ./a.out[0x400a5b]
    /lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xed)[0x7fe81d81b76d]
    ./a.out[0x4008d9]
    ======= Memory map: ========
    ....
    zsh: abort (core dumped)  ./a.out
    

    Test 4

    construct
    destroy
    destroy
    destroy
    destroy
    destroy
    destroy
    destroy
    destroy
    ...
    destroy
    destroy
    *** glibc detected *** ./a.out: free(): invalid pointer: 0x00000000016f6008 ***
    ======= Backtrace: =========
    /lib/x86_64-linux-gnu/libc.so.6(+0x7eb96)[0x7fa9001fab96]
    ./a.out[0x400a18]
    /lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xed)[0x7fa90019d76d]
    ./a.out[0x4008d9]
    ======= Memory map: ========
    ...
    zsh: abort (core dumped)  ./a.out
    
    0 讨论(0)
  • 2020-11-22 01:42

    For array of POD it will not leak (with the most compilers). For example, MSVC generates identical code for delete and delete[] for array of POD.

    Personally, I think C/C++ could be without operator delete[]. Compiler knows object size and allocated memory size is known at runtime, thus it is very simple to know is a pointer array or not and dispose memory in a right way.

    EDIT:

    OK, guys. Can you test at your compiler and say whether it leak?

    Try to think as a compiler developer. We have new, new[], delete, delete[]. Each new has its own delete. Seems perfect and complete. Let's see what is going on when you call delete[]?

    1. call vector destructor for an object
    2. actual free memory
    

    What is destructor for POD? Nothing! So, calling delete for array of POD will not leak! Even if it breaks the standard. Even if it is not recommended.

    EDIT2:

    This is disassembly code generated by VS2008:

    operator delete[]:
    78583BC3  mov         edi,edi 
    78583BC5  push        ebp  
    78583BC6  mov         ebp,esp 
    78583BC8  pop         ebp  
    78583BC9  jmp         operator delete (78583BA3h) 
    
    0 讨论(0)
  • 2020-11-22 01:43

    Using delete operator on allocations with new T[n] is undefined and will vary from compiler to compiler. AFAIK, MSVC compiler for example will produce different code than GCC.

    If A points to an array that was allocated via new T[n], then you must delete it via delete[] A. The difference between delete and delete[] is straightforward - the former destroys a scalar object and the latter destroys an array.

    0 讨论(0)
  • 2020-11-22 01:53

    It will usually not leak because in case of POD destructors are trivial and there's no need for invoking them so delete just deallocates memory occupied by the array. Memory deallocation requires just a pointer value so it will be returned to the heap. The array accopies a contiguous block of memory and so the deallocation can be sucessful just as if it was a deallocation of a single element.

    But don't rely on this since it is undefined behaviour. Maybe it works allright, maybe something horrible happens, works on this compiler, doesn't work on another and many people thank you for planting an error.

    See this answer for details.

    0 讨论(0)
  • 2020-11-22 01:53

    delete : calls the appropriate destructor only for the element pointed to (if needed), then frees the memory chunk

    delete[] : calls the appropriate destructors for each element in its array (if needed), then frees the memory chunk

    0 讨论(0)
提交回复
热议问题