2

Almost all C-type objects from C-libraries have some custom deleters, e.g. IplImage* from OpenCV has the cvReleaseImage(IplImage**) deleter function. In C++, I want my code in a way that it always ensures that every object gets finally deleted.

I guess it makes most sense to somehow use std::shared_ptr and its custom deleter functionality.

One example / maybe possible solution is in this question where I would just use shared_ptr<IplImage> but with a specialised version of default_delete<IplImage>. But see the answers there about the drawbacks: it is not guaranteed by the C++ standard that shared_ptr will use default_delete as the default deleter and I'm not allowed to specialize default_delete as I wish (see here).

Another solution would be something like this:

shared_ptr<IplImage> makeIplImage(IplImage* ptr) {
    return shared_ptr<IplImage>(ptr, default_delete<IplImage>()); // using my specialised default_delete
}

But then I must be careful to never forget to call makeIplImage when I want to wrap my IplImage*.

Again another solution would be to write my own wrapper object class, like

class IplImageObj {
    shared_ptr<IplImage> ptr;
public:
    IplImageObj(IplImage* img) : ptr(img, default_delete<IplImage>()) {} // again using my specialised default_delete
    // ...
};

I haven't really seen that much such solutions in the wild. Is it a bad idea to use them? If so, then I guess I'm missing something, but what? Or what is the most common/senseful way?

Community
  • 1
  • 1
Albert
  • 65,406
  • 61
  • 242
  • 386
  • I have no idea what's the most common, but I'd say go with the wrapper. Because if you need to encapsulate allocation/deletion, there are likely other things you want to encapsulate as well. It might be sensible to wrap the whole C library usage up in such a class. – Lundin Nov 29 '13 at 11:02
  • you can adapt `boost::intrusive_ptr` rather easily or you should write your own smart_ptr. I would go for writing the ptr handler, all standard or boost implementation lack features. The biggest flaw i've seen in them is that you can't associate the handling class with the pointer it holds to detect hanging references. – Raxvan Nov 29 '13 at 11:05
  • @Raxvan: Thanks for the suggestion. I think `instrusive_ptr` makes only sense if there is some refcounting already in place, but in most cases (also for `IplImage`), there is not. About the associating: In the Boost docs about `shared_ptr` [here](http://www.boost.org/doc/libs/1_55_0/libs/smart_ptr/sp_techniques.html#from_this), they suggest to use a `weak_ptr` for this case (if I understood you correctly). – Albert Nov 29 '13 at 11:32

1 Answers1

0

A wrapper seems like a good approach. If you define a destructor for a C++ class, then it can release the memory for you. The destructor gets called automatically when your class goes out of scope, so that should give you the piece of mind you're after. You could also implement checks for NUL ptr or dangling ptr inside the destructor, if that is useful in the memory-cleanup process.

class IplImageObj {
    IplImage* ptr;
    ~IplImageObj(){ /* The destructor: you can call cvReleaseImage from here  */}
public:
    IplImageObj(IplImage* img): ptr(img){}
    // ...
};

In the snippet above the data member ptr is private, so you'd probably want accessor functions in order to do anything with it.

My C++ lecturer was strongly against public declaration of data members in a class. If you want to make data members public, then struct has all the functionality of class nowadays, and people are more tolerant of public access of data members...

GnomeDePlume
  • 1,642
  • 2
  • 15
  • 31