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

后端 未结 24 2954
暗喜
暗喜 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 12:41

    As highlighted in other posts:

    1) Calls to new/delete allocate memory and may call constructors/destructors (C++ '03 5.3.4/5.3.5)

    2) Mixing array/non-array versions of new and delete is undefined behaviour. (C++ '03 5.3.5/4)

    Looking at the source it appears that someone did a search and replace for malloc and free and the above is the result. C++ does have a direct replacement for these functions, and that is to call the allocation functions for new and delete directly:

    STRUCT* pStruct = (STRUCT*)::operator new (sizeof(STRUCT) + nPaddingSize);
    // ...
    pStruct->~STRUCT ();  // Call STRUCT destructor
    ::operator delete (pStruct);
    

    If the constructor for STRUCT should be called, then you could consider allocating the memory and then use placement new:

    BYTE * pByteData = new BYTE[sizeof(STRUCT) + nPaddingSize];
    STRUCT * pStruct = new (pByteData) STRUCT ();
    // ...
    pStruct->~STRUCT ();
    delete[] pByteData;
    
    0 讨论(0)
  • 2021-02-14 12:43

    You're sort of mixing C and C++ ways of doing things. Why allocate more than the size of a STRUCT? Why not just "new STRUCT"? If you must do this then it might be clearer to use malloc and free in this case, since then you or other programmers might be a little less likely to make assumptions about the types and sizes of the allocated objects.

    0 讨论(0)
  • 2021-02-14 12:45

    It's always best to keep acquisition/release of any resource as balanced as possible. Although leaking or not is hard to say in this case. It depends on the compiler's implementation of the vector (de)allocation.

    BYTE * pBytes = new BYTE [sizeof(STRUCT) + nPaddingSize];
    
    STRUCT* pStruct = reinterpret_cast< STRUCT* > ( pBytes ) ;
    
     // do stuff with pStruct
    
    delete [] pBytes ;
    
    0 讨论(0)
  • 2021-02-14 12:45

    Use operator new and delete:

    struct STRUCT
    {
      void *operator new (size_t)
      {
        return new char [sizeof(STRUCT) + nPaddingSize];
      }
    
      void operator delete (void *memory)
      {
        delete [] reinterpret_cast <char *> (memory);
      }
    };
    
    void main()
    {
      STRUCT *s = new STRUCT;
      delete s;
    }
    
    0 讨论(0)
  • 2021-02-14 12:45

    ericmayo.myopenid.com is so wrong, that someone with enough reputation should downvote him.

    The C or C++ runtime libraries are managing the heap which is given to it in blocks by the Operating System, somewhat like you indicate, Eric. But it is the responsibility of the developer to indicate to the compiler which runtime calls should be made to free memory, and possibly destruct the objects that are there. Vector delete (aka delete[]) is necessary in this case, in order for the C++ runtime to leave the heap in a valid state. The fact that when the PROCESS terminates, the OS is smart enough to deallocate the underlying memory blocks is not something that developers should rely on. This would be like never calling delete at all.

    0 讨论(0)
  • 2021-02-14 12:45

    I personally think you'd be better off using std::vector to manage your memory, so you don't need the delete.

    std::vector<BYTE> backing(sizeof(STRUCT) + nPaddingSize);
    STRUCT* pStruct = (STRUCT*)(&backing[0]);
    

    Once backing leaves scope, your pStruct is no longer valid.

    Or, you can use:

    boost::scoped_array<BYTE> backing(new BYTE[sizeof(STRUCT) + nPaddingSize]);
    STRUCT* pStruct = (STRUCT*)backing.get();
    

    Or boost::shared_array if you need to move ownership around.

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