Will this C++ code cause a memory leak (casting array new)

后端 未结 24 2956
暗喜
暗喜 2021-02-14 12:26

I have been working on some legacy C++ code that uses variable length structures (TAPI), where the structure size will depend on variable length strings. The structures are allo

相关标签:
24条回答
  • 2021-02-14 13:01

    @Matt Cruikshank You should pay attention and read what I wrote again because I never suggested not calling delete[] and just let the OS clean up. And you're wrong about the C++ run-time libraries managing the heap. If that were the case then C++ would not be portable as is today and a crashing application would never get cleaned up by the OS. (acknowledging there are OS specific run-times that make C/C++ appear non-portable). I challenge you to find stdlib.h in the Linux sources from kernel.org. The new keyword in C++ actually is talking to the same memory management routines as malloc.

    The C++ run-time libraries make OS system calls and it's the OS that manages the heaps. You are partly correct in that the run-time libraries indicate when to release the memory however, they don't actually walk any heap tables directly. In other words, the runtime you link against does not add code to your application to walk heaps to allocate or deallocate. This is the case in Windows, Linux, Solaris, AIX, etc... It's also the reason you won't fine malloc in any Linux's kernel source nor will you find stdlib.h in Linux source. Understand these modern operating system have virtual memory managers that complicates things a bit further.

    Ever wonder why you can make a call to malloc for 2G of RAM on a 1G box and still get back a valid memory pointer?

    Memory management on x86 processors is managed within Kernel space using three tables. PAM (Page Allocation Table), PD (Page Directories) and PT (Page Tables). This is at the hardware level I'm speaking of. One of the things the OS memory manager does, not your C++ application, is to find out how much physical memory is installed on the box during boot with help of BIOS calls. The OS also handles exceptions such as when you try to access memory your application does not have rights too. (GPF General Protection Fault).

    It may be that we are saying the same thing Matt, but I think you may be confusing the under hood functionality a bit. I use to maintain a C/C++ compiler for a living...

    0 讨论(0)
  • 2021-02-14 13:02

    Technically I believe it could cause a problem with mismatched allocators, though in practice I don't know of any compiler that would not do the right thing with this example.

    More importantly if STRUCT where to have (or ever be given) a destructor then it would invoke the destructor without having invoked the corresponding constructor.

    Of course, if you know where pStruct came from why not just cast it on delete to match the allocation:

    delete [] (BYTE*) pStruct;
    
    0 讨论(0)
  • 2021-02-14 13:03

    Rob Walker reply is good.

    Just small addition, if you don't have any constructor or/and distructors, so you basically need allocate and free a chunk of raw memory, consider using free/malloc pair.

    0 讨论(0)
  • 2021-02-14 13:04

    You'd could cast back to a BYTE * and the delete:

    delete[] (BYTE*)pStruct;
    
    0 讨论(0)
  • 2021-02-14 13:06

    Yes it will cause a memory leak.

    See this except from C++ Gotchas: http://www.informit.com/articles/article.aspx?p=30642 for why.

    Raymond Chen has an explanation of how vector new and delete differ from the scalar versions under the covers for the Microsoft compiler... Here: http://blogs.msdn.com/oldnewthing/archive/2004/02/03/66660.aspx

    IMHO you should fix the delete to:

    delete [] pStruct;
    

    rather than switching to malloc/free, if only because it's a simpler change to make without making mistakes ;)

    And, of course, the simpler to make change that I show above is wrong due to the casting in the original allocation, it should be

    delete [] reinterpret_cast<BYTE *>(pStruct);
    

    so, I guess it's probably as easy to switch to malloc/free after all ;)

    0 讨论(0)
  • 2021-02-14 13:07

    If you really must do this sort of thing, you should probably call operator new directly:

    STRUCT* pStruct = operator new(sizeof(STRUCT) + nPaddingSize);
    

    I believe calling it this way avoids calling constructors/destructors.

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