1

The following is the best "minimum working example" I can construct for now. I would like to understand if the following code leaks memory.

// Class CTest
class CTest {
  vector<int> Elements;
  CTest (vector<int>&);
  ~CTest ();
};
CTest::CTest (vector<int>& Elements_) {
  this->Elements = Elements_;
}
CTest::~CTest () {
}

// main
int main (int argc, char *argv[]) {
  vector<CTest> V;
  for (auto i = 0; i < 10; i++) {
    vector<int> U;
    for (auto j = i; j < i + 5; j++) U.push_back (j);
    V.push_back (*(new CTest (U)));
  }
  // Do whatever
  return 0;
}

Am I correct in thinking that since there isn't a corresponding invocation of delete for each invocation of new, this programme does indeed leak memory?

Bo Persson
  • 90,663
  • 31
  • 146
  • 203
Shredderroy
  • 2,860
  • 2
  • 29
  • 53

4 Answers4

9

Yes, there is a memory leak. push_back copies its argument, so the original is lost forever (there is no longer a pointer to it).

Oliver Charlesworth
  • 267,707
  • 33
  • 569
  • 680
3

Yes, you are correct. Moreover, your code is of the type "trying very hard to get it wrong", since vector is already a dynamic container and you have no reason to perform another dynamic allocation for your element (just to have it copied).

There are many more ways to screw up. None of those are a particular design problem of C++, but there's simply a limit to what the language can stop you from doing. Some more examples:

int main(int argc, char **argv)
{
    new double;  // leak
    delete static_cast<void*>(&argc);  // doesn't belong to you
    int a = *static_cast<int const *>(0x42); // not a valid pointer

    { T x; x.~T(); }  // call destructor of non-existent object

    { T y; y.~T(); new (static_cast<void*>(&y) T(); }
                   // impossible to recover from exception in T::T()
}

Fortunately, it is almost always fairly obvious that you're doing something you're not supposed to.

Kerrek SB
  • 464,522
  • 92
  • 875
  • 1,084
  • Instead of a playbook of other ways to screw up, wouldn't an example of how to correct the code in the Q be a better use of this space? – David Heffernan Mar 17 '12 at 01:18
  • @DavidHeffernan: You mean "how to use `vector`?" Nah, I think the OP knows that. – Kerrek SB Mar 17 '12 at 01:20
  • "None of those are a particular design problem of C++, but there's simply a limit to what the language can stop you from doing." Naw, it's just that C++ (and most mainstream languages) have a terrible type system. Given a stronger type system it's entirely possible to guarantee, through type checking, that the program contains none of the errors you demonstrate. – GManNickG Mar 17 '12 at 03:01
  • @GManNickG: Perhaps... but can it be done without sacrificing expressiveness? Do you know of a language that doesn't let you write insane things like these but still gives you the same amount of control? – Kerrek SB Mar 17 '12 at 09:04
  • @KerrekSB: [ATS](http://www.ats-lang.org/), but the use of such type systems for system's programming is still new, so the language is a bit rough to work in. Of course there's things like Haskell and (Dependent) ML, but those aren't system programming languages. – GManNickG Mar 17 '12 at 19:09
0

Yes, that is correct. You don't deallocate the assignments made with new. Also, you don't need dynamic allocation within an already dynamic container.

0

Yes, it is leaking but just because you are trying too hard.

Using this code to populate the V vector

V.push_back(CTest(U));

will do what need, without any leaks.

Generally, the standard containers will manage the memory for you (without leaks). You don't have to bother.

Bo Persson
  • 90,663
  • 31
  • 146
  • 203