DevX Home    Today's Headlines   Articles Archive   Tip Bank   Forums   

Results 1 to 8 of 8

Thread: Using shared_ptr on a struct (not a pointer)

  1. #1
    Join Date
    Jan 2008
    Posts
    100

    Using shared_ptr on a struct (not a pointer)

    Hello,

    I am still mashing away at using shared_ptr and currently it has all been going well.

    However when dealing with a few Xlib stuff, I have noticed a small issue demonstrated by the following code (with my current solution)

    Code:
    std::tr1::shared_ptr<Colormap> colormap;
    Colormap _colormap = { 0 };
    
    // Create normal colormap using Xlib (C) function
    _colormap = XCreateColormap(display.get(), rootWindow, visualInfo->visual, AllocNone);
    
    // Add it to the shared_ptr (to protect it with RAII)
    colormap.reset(&_colormap, std::tr1::bind(XFreeColormap, display.get(), _colormap));
    
    // use *colormap.get() here...
    
    // XFreeColormap cleans up _colormap here as the shared_ptr goes off the stack..
    Because XCreateColormap returns a struct rather than a pointer to a struct, how to I use it with shared_ptr which AFAIK can only take a pointer as the template parameter.

    So what I have currently done, is use Colormap normally (_colorMap) but then add a reference of it to the shared_ptr using &.

    Is this a good idea? Since _colormap is made after the shared_ptr, would this means that it gets destroyed before the shared_ptr cleans up it's contained ptr leading to memory issues?

    How would you guys tackle this?

    Cheers!
    Last edited by kpedersen; 10-08-2011 at 10:32 AM.

  2. #2
    Join Date
    Dec 2003
    Posts
    3,366
    Not following all that well but putting a reference to something as a pointer into a pointer class that will eventually try to delete it is not sound. References are not really pointers, though they can be used more or less interchangably in syntax, up to the point where you new or delete them (or similar concepts). At that point, they fail to work properly. If this is not what you are doing, then I didnt really get your question (I see the order of operations issue too but that, I am not sure about).

  3. #3
    Join Date
    Jan 2008
    Posts
    100
    Hello jonnin,

    Yes, I think I explained it quite poorly. Sorry.

    Basically the XCreateColormap() returns an XColormap and XFreeColormap() takes an XColormap as a parameter.

    When used with shared_ptr, I cannot seem to specify XColormap, I can only seem to have XColormap* which is of course not compatible with these two functions.

    My solution was hacky and basically involved creating the struct raw, and then adding a pointer of it to the shared_ptr.

    Surely there is a better way?

    Is there some way of not letting shared_ptr<XColormap> turn it into a pointer? Kind of like std::vector where the programmer explicitly states if they want it to hold a pointer (e.g. vector<XColormap*>)

    Thanks!

  4. #4
    Join Date
    Dec 2007
    Posts
    401
    Wrap Colormap in a shim class and let the destructor take care of RAII, perhaps?

    Something like this:
    Code:
    struct colour_map : Colormap
    {
       colour_map( const colour_map& ) = delete ; // non-copyable (C++11)
       colour_map& operator= ( const colour_map& ) = delete ; // non-copyable (C++11)
    
       typedef std::shared_ptr<colour_map> pointer ;
    
       static pointer create( /* ... */ )
       {
          return pointer( new colour_map( /* ... */ ) ) ; 
       }
    
       private:
           colour_map( /* ... */ ) { *this = XCreateColormap( /* ... */ ) ; }
           ~colour_map() { XFreeColormap( /* ... */ ) ; }
    };
    And then:

    Code:
    colour_map::pointer pcolormap = colour_map::create( display.get(), rootWindow, visualInfo->visual, AllocNone) ;

  5. #5
    Join Date
    Jan 2008
    Posts
    100
    vijayan,

    I am not too keen on that idea since Xlib has loads of code like XColormap that would all require wrapping into classes. Instead I wanted to use something like shared_ptr and set a custom deleter to clean up the memory.

    I will also try out unique_ptr but I think that too makes the assumption that anything I pass in as a template parameter is going to be a pointer.

    Thanks, and any more suggestions are much appreciated!

  6. #6
    Join Date
    Dec 2003
    Posts
    3,366
    I suspect any sort of replacement for regular pointers will indeed want to turn it into a pointer (imagine that!). I do not know of a simple way to fix the problem -- you can either do the above in a template solution and wrap everything (ugg, a layer of bloat and confusion to do so little?) or write your own shared_ptr class that does exactly what you want (ugg, nonstandard, yet another pointer that isnt a pointer device to keep track of). I do not see a clean way out, due to the way the library you have is designed.

    Do you really have to wrap them all, or do you only use a small subset of the objects in the manner that requires the wrapper? It may be just 2-3 wrappers, not so bad?

    The easy way out, of course, is to just use a regular pointer, which takes no extra code, so long as you keep track of it all. I have yet to see a program that a normal pointer is not good enough to get the job done, apart from self inflicted design caused issues.

  7. #7
    Join Date
    Dec 2007
    Posts
    401
    > that would all require wrapping into classes.

    If the implementation supports variadic templates, you can have just one class to generate all the wrappers.

    > So what I have currently done, is use Colormap normally (_colorMap),
    > but then add a reference of it to the shared_ptr using &.
    > Is this a good idea?
    > would this means that it gets destroyed before the shared_ptr cleans up

    This is a perfectly workable idea; std::shared_ptr<> would use the deleter function and nothing else for clean up.

  8. #8
    Join Date
    Jan 2008
    Posts
    100
    Quote Originally Posted by jonnin View Post
    I suspect any sort of replacement for regular pointers will indeed want to turn it into a pointer (imagine that!).
    I see the logic here, but it is very common for C to use context structs or typedefs that don't go to the heap. I am suprised that std::tr1::shared_ptr did not compensate for this. For example in std::vector<XColorMap> I don't need to pass a pointer into this. Perhaps an obscene solution would be to put the vector into the shared_ptr, add the XColorMap to the vector, and then set the deleter function :)

    Quote Originally Posted by jonnin View Post
    Do you really have to wrap them all, or do you only use a small subset of the objects in the manner that requires the wrapper? It may be just 2-3 wrappers, not so bad?
    I guess I am worried that if a program becomes larger, I will end up having to wrap too much stuff.

    Quote Originally Posted by jonnin View Post
    The easy way out, of course, is to just use a regular pointer.
    I don't know if I dare! ;)

Similar Threads

  1. Adjacecny Lists C++
    By KouRaGe in forum C++
    Replies: 26
    Last Post: 04-07-2008, 04:41 AM
  2. Replies: 7
    Last Post: 01-11-2007, 12:27 PM
  3. Replies: 10
    Last Post: 07-24-2006, 05:57 AM
  4. pointer to an NMTREEVIEW struct in VB
    By Crispin Wright in forum VB Classic
    Replies: 10
    Last Post: 08-10-2001, 06:38 AM
  5. pointer to an NMTREEVIEW struct in VB
    By Crispin Wright in forum VB Classic
    Replies: 0
    Last Post: 08-06-2001, 02:40 PM

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
HTML5 Development Center
 
 
FAQ
Latest Articles
Java
.NET
XML
Database
Enterprise
Questions? Contact us.
C++
Web Development
Wireless
Latest Tips
Open Source


   Development Centers

   -- Android Development Center
   -- Cloud Development Project Center
   -- HTML5 Development Center
   -- Windows Mobile Development Center