delete vs explicit call of destructor

Viewed 512

In c++ calling delete on an object allocated with new calls the destructor of the class, and release the memory. Would there be any difference if, instead of deleting the object, one calls explicitly its destructor and then free the memory?

Consider, e.g., the following example.

#include <iostream>

struct A {
  int i;
  ~A() { std::cout << "Destructor, i was " << i << std::endl; }
};

int main()
{
  A* p = new A{3};
  p->~A();
  free(p);

  return 0;
}

Compiling the code with g++ 7.3.0 and clang 6.0.1, and with -Wextra -Wall -pedantic does not raise any warning. The output of the program, as expected is

Destructor, i was 3

Running the program with valgrind/memcheck gives an error of mismatched free/delete:

==27743== Memcheck, a memory error detector
==27743== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==27743== Using Valgrind-3.14.0 and LibVEX; rerun with -h for copyright info
==27743== Command: ./destructor
==27743== 
Destructor, i was 3
==27743== Mismatched free() / delete / delete []
==27743==    at 0x4C3033B: free (vg_replace_malloc.c:530)
==27743==    by 0x4009FC: main (in /tmp/destructor)
==27743==  Address 0x5bbac80 is 0 bytes inside a block of size 4 alloc'd
==27743==    at 0x4C2F77F: operator new(unsigned long) (vg_replace_malloc.c:334)
==27743==    by 0x4009DA: main (in /tmp/destructor)
==27743== 
==27743== 
==27743== HEAP SUMMARY:
==27743==     in use at exit: 0 bytes in 0 blocks
==27743==   total heap usage: 3 allocs, 3 frees, 73,732 bytes allocated
==27743== 
==27743== All heap blocks were freed -- no leaks are possible
==27743== 
==27743== For counts of detected and suppressed errors, rerun with: -v
==27743== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)

However, there is no memory leak.

I know of course that the standard way to dispose of the object p in the code above is to call delete. My question is more a formal one:

  • Is delete fully equivalent to a call to destructor and a free? Does the standard specify this, or I am running into UB with the code above?
1 Answers

While it is legal to explicitly call the destructor the cases where you will want to do so are very rare (std::vector for example where objects are constructed and destructed within a larger buffer).

Note that you should always match allocators with the appropriate memory release, malloc/free, new/delete, etc. While it is typical for operator new() to rely on malloc under the hood there is no requirement that it do so and in that case your mismatch would have undefined results.

Related