The object itself (this) is it a leak if its constructor throws?

if the ctor throws, then the object this has already received the memory (some new or alloc has been executed)... so, does the object this leak?

the only possible way that it didn't leak is if free is called upon ctor throw!!


this happens even if this is an empty class -- no non-static data members!

Correct??
I know the destructor is not called when constructor throws...
Last edited on
If the constructor throws the memory will be freed so there is no memory leak. Already constructed data members will have their destructors called.
There's no memory leak. The memory for the object is returned by new.

If you inspect the generated code for this program:
1
2
3
bool g(); 
struct a { a() { if (g()) throw 0; } }; 
a* f() { return new a; }

You can see that it conditionally calls operator delete.
https://godbolt.org/z/4sjKWE8f4

For example:
f():
        push    rbp
        push    rbx
        sub     rsp, 8
        mov     edi, 1
        call    operator new(unsigned long)
        mov     rbx, rax
        call    g()
        test    al, al
        jne     .L6
        mov     rax, rbx
        add     rsp, 8
        pop     rbx
        pop     rbp
        ret
.L6:
        mov     edi, 4
        call    __cxa_allocate_exception
        mov     rdi, rax
        mov     DWORD PTR [rax], 0
        mov     edx, 0
        mov     esi, OFFSET FLAT:_ZTIi
        call    __cxa_throw
        mov     rbp, rax
        mov     esi, 1
        mov     rdi, rbx
        call    operator delete(void*, unsigned long)
        mov     rdi, rbp
        call    _Unwind_Resume
But the destructor is not called when constructor throws...correct??
Last edited on
Right. The destructor isn't called, because the object's lifetime doesn't start until its constructor is complete.

That being said, member and base class subobjects get destroyed provided they are already within their lifetime when the exception is thrown.
You have to be careful with constructors. Most of the time they Do The Right Thing™.

The problem is if you start managing your own resources.

For example:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
struct leaks_memory
{
  char * s;

  leaks_memory()
  : s{nullptr}
  {
    s = new char[40];
    throw "something";
  }

  ~leaks_memory()
  {
    if (s) delete [] s;
  }
};

That’s pretty academic-looking, but it easily happens when managing some complex resources.

Here’s another leaky class:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
struct leaks_resources
{
  FILE * f;

  leaks_resources()
  : f{nullptr}
  {
    f = fopen( "a-valid-file.txt", "r" );
    throw "something";
  }

  ~leaks_resources()
  {
    if (f) fclose( f );
  }
};

There are all kinds of ways you can write a constructor to fail.

Fortunately, modern C++ provides a lot of abstractions to help with that. Here is the first example again, except it does not leak memory:

1
2
3
4
5
6
7
8
9
10
struct doesnt_leak_memory
{
  std::unique_ptr <char[]> s;

  doesnt_leak_memory()
  {
    s.reset( new char[40] );
    throw "something";
  }
};

Hope this helps.
The pitfalls in leaks_resources and leaks_memory exist and are are common outside of constructors too.
Excellent comments! Thank you again!!
Registered users can post here. Sign in or register to post.