I have some shared pointer shared_ptr<T> pointer1(new T(1));.
Now, in some other part of code I have an explicit copy of pointer2 (guess it would be stored in a std::map or some other container). Let's say that copy was done like map.insert(make_pair(key1, pointer1));.
I am using that second copy only to precache some data and this means that if the main pointer is already invalid, there is no need to store the second pointer. What should I do in this case?
Is there any way to force the memory deallocation for the second pointer if I know that pointer1 became invalid in some other part of my code?
Or should I take the ugly way - from time to time check my map for pointers which have ptr.unique() set to true and destruct them?
Maybe some alternatives / advices?
Edit - plain code sample
std::map<int, shared_ptr<int> > map;
{
shared_ptr<int> pointer1(new int(5));
map.insert(std::make_pair(0, pointer1));
}
Is there any way / trick to make map contain <0, shared_ptr[NULL]> instead of <0, shared_ptr[5]> after these operations happen?
Thanks
It sounds like this is a task for weak_ptr:
http://www.boost.org/doc/libs/1_40_0/libs/smart_ptr/weak_ptr.htm
Try putting them in your table instead of a shared_ptr.
I am using that second copy only to precache some data and this means that if the main pointer is already invalid, there is no need to store the second pointer. What should I do in this case?
You should look at boost::weak_ptr
If the associated shared_ptr has been reset then the weak_ptr knows about it.
Is there any way to force the memory deallocation for the second pointer if I know that pointer1 became invalid in some other part of my code?
Don't think so.
But if you use weak pointer this will not be required.
Related
talking about C++.
Let's say I have an array of pointers to objects.In position Array[6] for example,I want to replace the object pointed by, with another of the same type.
Which is the wisest way?
1.
delete Array[6];
Array[6]=new Object(...);
2.
Array[6]=NULL;
Array[6]=new Object(...);
3.
Array[6]=new Object(...);
Or something else I'm missing.Waiting for advice,thank you!!
EDIT:
question:
Do you want to delete the object pointed to by Array[6]? If so, do delete Array[6];. If not, don't delete Array[6];. I'm not sure what there is to be confused about there.
answer:
Yes,it's what you've mentioned that I want. I want the object pointed by Array[6] to "disappear" and make a new one there.
My other problem: I want to delete some objects of the Array in a function, but in another I want to access them so I have to check.
Which will be my check?
Maybe:
if (Array[i]==NULL){..} or is it wrong since I have not "NULLed" it?
2 and 3 are likely to cause memory leaks. As such I would suggest 1, or use array of smart pointers and reset them with new object.
Number 1 is very different. The other 2 are basically the same (but with more or less typing)
Do #1 if the array is the owner of the object, ie you need to free the memory. Otherwise do #2 or 3
And anyway use std::vector and std::shared_ptr
If feels like you come from languages that do magic with references (like c# or Java) where assugining null to a pointer actually does someting. Not so in c++ (unless you use smart pointers and containers as I said before)
So I have some C++ classes that use a map and key class for a sort of data structure. In my insert method I use the typical map.insert. I want this function to return a pointer so I can modify some values (not the one used for comparison) inside the element inserted. So I was wondering if this is safe to this..
template<typename T>
NodeT<T> * TreeT<T>::
MakeNode(PointT point)
{
NodeT<T> * prNode = new NodeT<T>;
//set the contents for the node
prNode->SetNode(point, m_dTolerance);
//Create the key class using the
VectorKey key(point, m_dTolerance);
//Store the key,node as a pair for easy access
return_val = m_tree.insert( pair<VectorKey, NodeT<T> >(key, *prNode) );
if (return_val.second == false)
//if return_val.second is false it wasnt inserted
prNode = NULL;
else
//it was inserted, get a pointer to node
prNode = &(return_val.first->second); //is this safe if I plan to use it later?
return prNode;
}
I seemed to learn the hard way that my original pointer (the one I created with new), was pointing to the wrong element after the insert. Can anyone tell me why that is? So I used the return_val iterator to get the right pointer. I kinda dont want to return an iterator but if its safer then I do...
Thanks!
You seems to have troubles in your code with pointers and values. First you allocate an object on a heap ( with new Node )
Then you use a copy of that object to sore within your map.
PS. And then you loose original object forever as do not free memory which leads to memory leak.
In your case - it is invalid because you return pointer to object which can be deleted at any time ( for example next time you add something to your map and map decides to reallocate it's tree, so it will copy objects to different places ).
Storing pointers as map values prevents this. The only thing you need to remember to clear them up when removing object from map and when removing map itself.
The easy way to handle that would be using smart pointers (boost::shared_ptr for example ) or smart map class (boost::ptr_map for example ).
To fix that - use pointers everywhere ( store a pointer as a map value ).
This way - you will be able to return pointer from this function and it will be valid.
So just turn your map to map*> and this should fix most of your problems.
Do not forger to delete objects when erasing them from the map.
This code sample is interesting because contains a several things wrongs or to avoid.
Implementation
The most important things are been said (mainly by Bogolt):
You are leaking memory, because allocate NodeT<T> from the heap and never free it again, since map will allocate a copy of the object, not the pointer. Indeed, you specify as parameter *prNode, not prNode.
You use the heap to allocate the object (will be copied into the map), but you assume you always allocate the object. Despite it will be the very most probably case, that is not alway true: new operator would be return null or throw a bad_alloc exception. The code does not handle it.
Anyway, you use the heap when is not really needed. (And you see the problems are you intriducing because that). You can just create the object in the stack and then insert into the map, avoiding the previous problems and typing less code.
Design
The function returns a pointer to the element in the map. Depending the program, is possible this is safe. But what happens if the code reference the pointer when the object is removed from the map? Better, if you are returning pointer, do not return a raw pointer. Use smart pointer (shared_ptr in this case) instead. Using shared_ptr you will have not problems with the object life.
Other reason to use smart pointers: because the insertion into the map imply a copy of the element, you are imposing a requirement to NodeT<T>: it has to be copy constructible. May be this requirement is not important for performance, but may be in other circumstances copying the object have drawbacks. If you use smart pointer (or boost::ptr_map), the object will be created just once and is not copied.
Style
Just some suggestion, but not too important:
instead type pair<VectorKey, NodeT<T> >(key, *prNode), type make_pair(key, *prNode). The code is more compact and clearer typing less.
Well I'd say that depends on is your map alive longer than anything that could use (and store) the pointer.
If yes, (ie, it's in some sort of singleton), you could go with it, but not very safe anyway since any code could delete the pointer.
The best option is to store boost::shared_ptr (or std:: since c++11) instead of raw pointers in your mapn and return only a weak_ptr after insertion.
That way, you're sure no other code can delete your pointer as long as the map holds it, and that no one can use a pointer that has been erased from the map.
If I have a boost::shared_array<T> (or a boost::shared_ptr<T[]>), is there a way to obtain a boost::shared_ptr<T> which shares with the array?
So for example, I might want to write:
shared_array<int> array(new int[10]);
shared_ptr<int> element = &array[2];
I know that I can't use &array[2], because it just has type int *, and it would be dangerous for shared_ptr<int> to have an implicit constructor that will take that type. Ideally shared_array<int> would have an instance method on it, something like:
shared_ptr<int> element = array.shared_ptr_to(2);
Unfortunately I can't find anything like this. There is an aliasing constructor on shared_ptr<int> which will alias with another shared_ptr<T>, but it won't allow aliasing with shared_array<T>; so I can't write this either (it won't compile):
shared_ptr<int> element(array, &array[2]);
//Can't convert 'array' from shared_array<int> to shared_ptr<int>
Another option I played with was to use std::shared_ptr<T> (std instead of boost). The specialisation for T[] isn't standardised, so I thought about defining that myself. Unfortunately, I don't think that's actually possible in a way that doesn't break the internals of the aliasing constructor, as it tries to cast my std::shared_ptr<T[]> to its own implementation-specific supertype, which is no longer possible. (Mine is currently just inheriting from the boost one at the moment.) The nice thing about this idea would have been that I could implement my instance shared_ptr_to method.
Here's another idea I experimented with, but I don't think it's efficient enough to be acceptable as something we're potentially going to use throughout a large project.
template<typename T>
boost::shared_ptr<T> GetElementPtr(const boost::shared_array<T> &array, size_t index) {
//This deleter works by holding on to the underlying array until the deleter itself is deleted.
struct {
boost::shared_array<T> array;
void operator()(T *) {} //No action required here.
} deleter = { array };
return shared_ptr<T>(&array[index], deleter);
}
The next thing I'm going to try is upgrading to Boost 1.53.0 (we currently only have 1.50.0), using shared_ptr<T[]> instead of shared_array<T>, and also always using boost instead of std (even for non-arrays). I'm hoping this will then work, but I haven't had a chance to try it yet:
shared_ptr<int[]> array(new int[10]);
shared_ptr<int> element(array, &array[2]);
Of course I'd still prefer the instance method syntax, but I guess I'm out of luck with that one (short of modifying Boost):
shared_ptr<int> element = array.shared_ptr_to(2);
Anyone else have any ideas?
You are doing strange stuff.
Why do you need shared_ptr to element? Do you want element of array be passed somewhere else and hold down your array from removal?
If yes, than std::vector<shared_ptr<T>> is more suited for that. That solution is safe, standard and has fine granularity on objects removal
boost::shared_ptr does not seem to support this nativly. Maybe you can work around this with a custom deleter. But std::shared_ptr offers a special constructor to support what you want:
struct foo
{
int a;
double b;
};
int main()
{
auto sp1 = std::make_shared<foo>();
std::shared_ptr<int> sp2 (sp1,&sp1->a);
}
Here, sp1 and sp2 share ownership of the foo object but sp2 points to a member of it. If sp1 is destroyed, the foo object will still be alive and sp2 will still be valid.
Here's what I did in the end.
I made my own implementation of shared_array<T>. It effectively extends shared_ptr<vector<T>>, except it actually extends my own wrapper for vector<T> so that the user can't get the vector out. This means I can guarantee it won't be resized. Then I implemented the instance methods I needed - including weak_ptr_to(size_t) and of course operator[].
My implementation uses std::make_shared to make the vector. So the vector allocates its internal array storage separately from the control block, but the vector itself becomes a member of the control block. It's therefore about equivalent to forgetting to use std::make_shared for a normal type - but because these are arrays, they're likely to be largeish and few, so it's less important.
I could also create an implementation that's based on shared_ptr<T> but with default_delete<T[]> or whatever is required, but it would have to allocate the array separately from the control block (so there's not much saving versus vector). I don't think there's a portable way to embed a dynamically sized array in the control block.
Or my implementation could be based on boost::shared_array<T>, and use the custom deleter when taking element pointers (as per the example in the question). That's probably worse in most cases, because instead of a one-time hit allocating the array, we get a hit every time we take an aliased pointer (which could happen a lot with very short-lived ones).
I think the only reasonable way to get it even more optimal would be to use the latest boost (if it works; I didn't get as far as trying it before I changed my mind, mainly because of the desire for my own instance members). And of course this means using the boost ones everywhere, even for single objects.
But, the main advantage with what I went with is Visual Studio's debugger is (I'm told) good at displaying the contents of std::shared_ptrs and std::vectors, and (we expect) less good at analysing the contents of boost things or custom things.
So I think what I've done is basically optimal. :)
ok, so I got a doubt, I want to know if this is possible:
I'm using a database, with generic data (strings, ints, bools, etc...). Whenever an object is constructed or a member of an object is modified, I have to query the database with the specific action (SELECT or UPDATE).
First of all, this isn't a DB related question, my real problem is that I have a ptr_vector which holds boost::any's pointers to members of the object. In code something like this:
class Enemy{
private:
//some private data...
public:
auto_ptr<int> ID_Enemy;
auto_ptr<string> Enemy_Name;
//miscellaneous methods...
};
then I pass the members I want to modify to a function of another miscellaneous class which takes as argument a boost::any*:
misc_class.addValues((boost::any*)(ID_Enemy.get()));
misc_class.addValues((boost::any*)(Enemy_Name.get()));
that same class accepts the any*, and does the following:
auto_ptr<boost::any> val2(val); //being val, the passed any*
Enemy_Values.push_back(val2);
Enemy_Values is a ptr_vector. So when I access this misc_class which has Enemy_Values as member, I want to change the value to which an auto_ptr inside is pointing:
misc_class.Enemy_Values[0] = (boost::any)(69);
And here, I get a violation error. I've tried many things, and someone told me that I shouldn't be using containers of auto_ptr or converting back and forth with boost::any. Is this that I am doing possible, or there is a better and more intuitive way?
Thanks in advance.
(boost::any*)(ID_Enemy.get()) performs a reinterpret_cast since you are casting unrelated pointer types. This means you get an invalid pointer to an any, pointing to what is really an integer.
Instead, construct a temporary boost::any object and pass it by reference to addValues:
misc_class.addValues(boost::any(ID_Enemy.get());
Your use of auto_ptr is in fact incorrect: auto_ptr deletes objects on the freestore but here we're dealing with locals instead. addValues merely needs to push the value of the any object into the vector:
Enemy_Values.push_back(val);
... and Enemy_Values should just be a std::vector.
You could do this with a ptr_vector and freestore-allocated boost::any objects, but that would be more complicated than necessary.
auto_ptr has a number of problems. Since you are already using boost, why not use boost::shared_ptr instead?
My program is crashing every time I try to store a COM pointer into a struct, and then later try to use the original pointer. I don't have debug access to tell exactly what's wrong.
pRend->cp = cpRT;
ID2D1SolidColorBrush *scBrush;
ERF(cpRT->CreateSolidColorBrush(D2D1::ColorF(D2D1::ColorF::CornflowerBlue), &scBrush));
It crashes on CreateSolidColorBrush. However, if I comment out pRend->cp = cpRT, it doesn't.
By the way, pRend->cp and cpRT are of type ID2D1HwndRenderTarget *.
Instead of assigning directly QI and then store i.e.,
pRend->cp = cpRT;
should be replaced with
cpRT->QueryInterface(&pRend->cp);
It's unclear how much code exists between when you assign it into the struct and later use it in CreateSolidColorBrush. If it's a non-trivial amount of time, it's possible that you have a reference counting issue.
Are you storing a raw pointer in the struct? If so, switch it to a CComPtr and see if the crash goes away.
For instance. If you had the following type definition for the value of pRend (call it Render) and the value pRend was destroyed before making the CreateSolidColorBrush call, you could see this behavior.
struct Render {
ID2D1HwndRenderTarget *pCt;
~Render() {
pCt->Release();
}
};
As it turns out, I managed to stop the crashing by allocating pRend with malloc. This is not a problem because I will call free when I don't need it anymore. I'm interested in why calling malloc fixes this though. I'm used to just doing Datatype * var; and then just using var. Is that bad?
It's a smart pointer. I'm guessing you're inadvertantly calling release on it. In particular, it's addressof operator (unary op&) is overriden to call Release().
See what happens if you instead assign it to a reference, an ID2D1HwndRenderTarget*&.
Obviously, if you assign to a reference, you won't be able to reseat it.