2

Consider the following program

#include <iostream>
#include <cstring>
#include <stdexcept>

class cmdline {
  char *stored_file = nullptr;

public:

  cmdline(const int argc, char const* const* argv) :
    stored_file(argc < 6 ? throw std::logic_error("Not enough parameters") : new char[std::strlen(argv[1]) + 1]) { }
  ~cmdline() { delete[] stored_file; }
};

int main(int argc, char *argv[])
{
  using namespace std;

  cmdline *p;

  try {
    p = new cmdline(argc, argv);
  }
  catch(const logic_error& err) {
    cout << err.what() << endl;
    exit(1);
  }

  return 0;
}

In the constructor of cmdline, an exception is thrown if the condition argc < 6 is realized. In this case I would have expected that no memory is allocated by the constructor.

When I run with valgrind --leak-check=full I get the errors:

==9845== 
==9845== HEAP SUMMARY:
==9845==     in use at exit: 190 bytes in 2 blocks
==9845==   total heap usage: 5 allocs, 3 frees, 73,926 bytes allocated
==9845== 
==9845== 46 bytes in 1 blocks are possibly lost in loss record 1 of 2
==9845==    at 0x4841F11: operator new(unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==9845==    by 0x4966049: allocate (new_allocator.h:137)
==9845==    by 0x4966049: std::string::_Rep::_S_create(unsigned long, unsigned long, std::allocator<char> const&) [clone .isra.0] (cow_string.h:3537)
==9845==    by 0x4966116: char* std::string::_S_construct<char const*>(char const*, char const*, std::allocator<char> const&, std::forward_iterator_tag) [clone .part.0] [clone .isra.0] (cow_string.h:3096)
==9845==    by 0x49664F7: std::logic_error::logic_error(char const*) (cow-stdexcept.cc:87)
==9845==    by 0x1093B9: cmdline::cmdline(int, char const* const*, int) (test.cpp:11)
==9845==    by 0x109267: main (test.cpp:22)
==9845== 
==9845== 144 bytes in 1 blocks are possibly lost in loss record 2 of 2
==9845==    at 0x48417AB: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==9845==    by 0x493BB44: __cxa_allocate_exception (eh_alloc.cc:284)
==9845==    by 0x1093A4: cmdline::cmdline(int, char const* const*, int) (test.cpp:11)
==9845==    by 0x109267: main (test.cpp:22)
==9845== 
==9845== LEAK SUMMARY:
==9845==    definitely lost: 0 bytes in 0 blocks
==9845==    indirectly lost: 0 bytes in 0 blocks
==9845==      possibly lost: 190 bytes in 2 blocks
==9845==    still reachable: 0 bytes in 0 blocks
==9845==                       of which reachable via heuristic:
==9845==                         stdstring          : 46 bytes in 1 blocks
==9845==         suppressed: 0 bytes in 0 blocks
==9845== 
==9845== For lists of detected and suppressed errors, rerun with: -s
==9845== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0)

Needless to say, test.cpp:11 is the line where stored_file is initialized.

What exactly is the origin of the leak?

francesco
  • 7,189
  • 7
  • 22
  • 49
  • @user253751 but the code in main has a ```catch``` for a ```logic_error``` exception... – francesco Mar 13 '23 at 20:40
  • 1
    yes, I misread. It seems to be saying the exception was leaked. I suppose that the exception would've been deleted at the end of the catch block, but the program exited before then. – user253751 Mar 13 '23 at 20:41
  • 1
    @user253751 ahhh, now I see, good catch! (pardon the pun :-) ). Indeed, if I substitute ```exit(1)``` with ```return 1```, the leak disappears. – francesco Mar 13 '23 at 20:42
  • 1
    Remove the call to `exit(1)` – PaulMcKenzie Mar 13 '23 at 20:42
  • 4
    [Probably relevant](https://stackoverflow.com/questions/7054685/are-destructors-run-when-calling-exit). – PaulMcKenzie Mar 13 '23 at 20:47

0 Answers0