Sign in to follow this  
_Sigma

boost::shared_array - deleting contents

Recommended Posts

_Sigma    792
I'm using boost::shared_array to hold an array of float*. However, I need to be able to potentially delete all this memory before the smart pointer goes out of scope. I will be replacing said array with a new one of (probably) different size. Is it safe to do this:
boost::shared_array<float> ptr(new float[500]);
delete[] prt.get();




Cheers.

Share this post


Link to post
Share on other sites
fpsgamer    856
Unfortunately that isn't possible (based on what you've described). Why don't you share an object that can resize such as boost::shared_ptr<std::vector<float> > ?

Share this post


Link to post
Share on other sites
_Sigma    792
I really don't need any of the vector overhead...So I would rather not go down that path.

Quote:
Unfortunately that isn't possible

The code I posted compiles and *seems* to run. What makes it not possible?
Quote:
(based on what you've described)

What would I have to describe to make this possible?

Ultimately I need this:

boost::shared_array<float> ptr;
// stuff
ptr = boost::shared_array<float>(new float[row*col]);
//stuff
delete[] ptr.get();
//stuff
ptr = boost::shared_array<float>(new float[new_row*new_col]);


I would like to have a smart pointer here (I'm looking for exception safety) - any recommendations so I can do the above?

Share this post


Link to post
Share on other sites
jyk    2094
You never want to invoke delete on the return value of get(). (Well, I suppose there are no 'nevers' in C++, but you know what I mean.)

With boost::shared_ptr, you would (I think) use the reset() function for this:
boost::shared_ptr<Foo> foo_p(new Foo);
foo_p.reset(new Foo); // The previously allocated 'Foo' is deleted
foo_p.reset(); // The previously allocated 'Foo' is deleted (and the shared pointer is now 'empty')
I assume shared_array works in a similar fashion (although I've never used it myself).

Share this post


Link to post
Share on other sites
fpsgamer    856
Quote:
Original post by jyk
You never want to invoke delete on the return value of get(). (Well, I suppose there are no 'nevers' in C++, but you know what I mean.)

With boost::shared_ptr, you would (I think) use the reset() function for this:
boost::shared_ptr<Foo> foo_p(new Foo);
foo_p.reset(new Foo); // The previously allocated 'Foo' is deleted
foo_p.reset(); // The previously allocated 'Foo' is deleted (and the shared pointer is now 'empty')
I assume shared_array works in a similar fashion (although I've never used it myself).


As long as he only wants exception safety and he doesn't intend for there to be any other smart pointers referencing that array, then that'll do it.

Share this post


Link to post
Share on other sites
ToohrVyk    1595

  • If you use shared pointer semantics, then you can't reliably destroy the shared object. This is because the object may be referenced by other pointers and must therefore be kept alive. What you can do is stop referencing the shared object and start referencing a new one. If nobody else references the old object, it will be destroyed.

  • The overhead of std::vector is smaller than the overhead of boost::shared_array, because there is no sharing involved. So, if you don't need sharing and instead just need control over a buffer of memory in an exception-safe way, using a vector is both semantically correct and more efficient.

Share this post


Link to post
Share on other sites
MaulingMonkey    1728
Quote:
Original post by _Sigma
The code I posted compiles and *seems* to run.

It will delete the buffer again when it hits the end of ptr's scope, invoking undefined behavior. In practice, it will definitely explode if your allocator tries to reuse that memory before the last shared_array instances goes out of scope. You can however release your claim early with ptr.reset(), which will invoke delete if it was the last shared_array instance owning that buffer.

Given that you've stated "replace", however, I'm guessing you almost certainly want boost::shared_ptr<std::vector<float> > here, assuming you actually need shared semantics, because that replacement won't be reflected in the other shared_array instances otherwise / as currently stands -- you share changes to the array, but you won't share changes to which array is being used with your current code. Of course, this is assuming you even need sharing semantics. If you don't, why the **** aren't you just using std::vector? 0_o.

Share this post


Link to post
Share on other sites
Oxyd    1157
Quote:
Original post by _Sigma
I really don't need any of the vector overhead...So I would rather not go down that path.


What overhead? You've got to pay the memory allocation cost, no matter if you do it yourself via new[] or let the allocator do it. And if the vector doesn't grow beyond its .capacity(), there's no overhead compared to raw arrays.

Share this post


Link to post
Share on other sites
_Sigma    792
Alright, I appreciate all the feedback. I assumed that calling delete[] was bad but I'm happy to know why.

Must admit my knowledge of STL isn't the strongest - can anyone explain why using a vector is going to give me exception safety with pointers?

I need thread safety and my current understanding is that STL does not guarantee this. I don't need to grow/shrink the vector after is is created; just need it to be safe to have multiple threads access and change items (different items).



Share this post


Link to post
Share on other sites
ToohrVyk    1595
Quote:
Original post by _Sigma
Must admit my knowledge of STL isn't the strongest - can anyone explain why using a vector is going to give me exception safety with pointers?
With pointers? The reason why people use the SC++L containers (and vectors in particular) is that they don't need to use pointers to reference dynamic sequences of data.

The SC++L containers are designed to be exception-safe: no matter when an exception is thrown, the container will remain in a valid state and, if an exception happens to leave the scope the container is defined it, the container's data will be cleared correctly. In short, there's no way you can use an exception to waste a container or lose its internal memory.

Of course, if you store pointers inside a container, then you have to take care of those pointers yourself.

Quote:
I need thread safety and my current understanding is that STL does not guarantee this.
This is an entirely different kind of thing, and neither SC++L containers nor boost shared array pointers offer thread-safety. If you think you will be accessing the same data from two threads, you need a lock (possibly using boost's mutex library).

Share this post


Link to post
Share on other sites
_Sigma    792
Quote:
Original post by ToohrVyknor boost shared array pointers offer thread-safety.

Ah. Now that is a bummer.

Quote:
The reason why people use the SC++L [...]

I apologize for my ignorance here - I just want to make sure I know what is going on.


std::vector<float> floats;
floats.reseve(1000000);


Is this allocated on the stack or heap? If it's stack - isn't this a bad thingTM given the huge size of what I'm allocating?

Share this post


Link to post
Share on other sites
Oxyd    1157
It's allocated using the supplied Allocator -- if you supply no allocator, it defaults to the one that allocates on the free store (AKA “heap”).

Share this post


Link to post
Share on other sites
_Sigma    792
Well shit, I wish I'd know that a while ago.

Alright, well I think this pushes me in the right direction. Many thanks!

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this