1

in C++, suppose there is a method in a Helper class which returns me a pointer to another object. I don't have any more information about this method except the method signature and the type of returned object. How to do memory management in this case?

I attempted to use smart pointer as this function below:

void f() {
   auto_ptr<SomeClass> p_someClass = p_Helper->getSomeclass();
   p_someClass->doSomething();
}

The memory allocated to p_someClass is deallocated as soon as f() goes out of scope. However, what if getSomeclass() doesn't allocate new memory but simply return a "singleton" pointer (and p_Helper is also singleton)? Then the next call to p_Helper->getSomeclass() will be in trouble.

What is the usual way to handle this issue, esp when there is very little documentation on the Helper class?

TommyQ
  • 501
  • 7
  • 18

5 Answers5

3

What does the documentation of the helper class say? That is the ultimate issue. You can't return a pointer or a reference without specifying its lifetime: if it's a pointer to something internal in the class, it might be the lifetime of the class object, but it could also have static lifetime (until the end of the program—this is the case of functions which return string literals as char const*), it might have some shorter lifetime (e.g. references returned by operator[] by the standard library containers), or the helper might expect you to delete it. The latter should be rare, however, in pure C++; the convention in such cases is to return std::auto_ptr (or std::unique_ptr if you have a very modern compiler). (In C, it was frequent to document that the returned pointer had to be freed by calling a specific function in the library which returned it. Without destructors, you have to do something to regain control at the end.)

In the absense of documentation, I'm tempted to say that the library is not usable. Still... supposing that it points to something internal and has the lifetime of the class is probably the most reasonable guess; it's the case which programmers most easily forget to document. Deleting it, or putting it in a smart pointer which will delete it, is probably not a good idea: enough has been said about ownership issues that it seems unlikely that a class author would fail to document the fact if you were supposed to delete it. (Note, however, that the lifetime issues remain even if you're not supposed to delete it.)

James Kanze
  • 150,581
  • 18
  • 184
  • 329
  • not to start a flame war, but this is precisely the reason I really hate C++. Not everyone is a library developer. Most of the time in the enterprise systems world, people write bad codes with no documentation. Yet poor documentation is never a real problem with Java --End of rant-- : p – TommyQ Jul 18 '12 at 07:43
  • @TommyQ I can't agree with you. I've had serious problems with poor or missing documentation in Java. The problem is language agnostic. (Even with regards to lifetime of an object; it's easy to end up with "zombie" objects in Java, whose lifetime has ended, but the object is still there.) – James Kanze Jul 18 '12 at 08:27
2

If you are not the author of the p_Helper class, first:

Singletons usually do not have public destructors so in that case that would not compile.

Second, if you 'just get' a bare pointer without any further information, there's no way to know if you can delete it or not. That information needs to be provided in documentation for you to use the function/method.

If you are designing p_Helper, then let it return the smart pointer, rather than a bare pointer. If the method creates a new resource for each call, I suggest unique_ptr, have a look here: Differences between unique_ptr and shared_ptr

Community
  • 1
  • 1
Johan Lundberg
  • 26,184
  • 12
  • 71
  • 97
  • Unfortunately the code compiles, and the documetation is nothing more than the method signature itself. Being concerned about memory leak, I wrapped the returned raw pointer with smart pointer, and get some "violation - attempt to read from free memory area" error later. – TommyQ Jul 18 '12 at 07:23
  • so it suggest returned pointer is either singleton or maybe even pointer to other static data - in both cases you mess up memory when you perform automatic delete. Maybe try valgrind (under linux) or other memory leak detection software on minor case and see if you get memory leak when you don't delete – Piotr Tkaczyk Jul 18 '12 at 07:25
  • Good suggestion @zodi, else contact the authors or try to read the code. – Johan Lundberg Jul 18 '12 at 07:30
  • @zodi Most likely, I think, is that the pointer points to some internal data in the helper object. So client code shouldn't delete it. But this still doesn't address the issue of lifetime: the pointer might be invalidated by calling some other function on the helper object, for example. (Think of the pointer returned by `std::vector<>::data()`.) – James Kanze Jul 18 '12 at 07:33
1

The typical approach to this scenario is to use reference counting and a smart pointer like shared_ptr that will usually take care of all reasonable cases.

sharptooth
  • 167,383
  • 100
  • 513
  • 979
  • reference counting won't work in this case either bc the Helper class returns a raw pointer. My question is more about how to know when to delete a pointer rather than which smart pointer to use. – TommyQ Jul 18 '12 at 07:27
  • That's a recipe for disaster if the pointer points to internal data in the class (which would be the most logical default assumption). – James Kanze Jul 18 '12 at 07:31
  • @James Kanze: Sure, that internal data must be a smart pointer to separate dynamically allocated object then. – sharptooth Jul 18 '12 at 07:34
  • @sharptooth Why? It's not in any of the actual cases I know. (`std::vector<>::data()`, `std::string::c_str()`, etc.) In application code, one of the more frequent cases is to return a pointer to an element in a map (or `NULL` if the element isn't present). Why all this insistence on dynamic allocation. – James Kanze Jul 18 '12 at 08:11
  • @JamesKanze: Sure, in these cases the container owns the stored data entirely. – sharptooth Jul 18 '12 at 08:51
1

You can use raw pointers in this case.

void f() {
   SomeClass *p_someClass = p_Helper->getSomeclass();
   p_someClass->doSomething();
}
inkooboo
  • 2,904
  • 1
  • 19
  • 24
1

You could do a quick test and compare the pointers returned by two calls to p_Helper->getSomeclass();

bool do_not_delete =  p_Helper->getSomeclass() ==  p_Helper->getSomeclass();

If both pointers are equal, you are probable getting a pointer that is meant to be a (maybe optional) reference.

hth Torsten

Torsten Robitzki
  • 3,041
  • 1
  • 21
  • 35