I've got these lines:
typedef boost::shared_ptr<A> A_SPtr;
void *f(void* var){ ...
and i want to be able to do something like this:
A_SPtr instance = (void*)(var);
how can i do it?
Also, how can i cast the other way around meaning from the shared_ptr to void*?
Just cast pointers to shared pointers to and from void *.
shared_ptr to void *:
f (reinterpret_cast<void *>;(&A_SPtr));
void * back to shared_ptr:
A_SPtr instance = * reinterpret_cast(boost::shared_ptr<A>*)(var);
CAUTION: This passes a pointer to the shared pointer to the thread. This will not work if the shared pointer does not remain in existence through the life of the thread function – otherwise, the thread will have a pointer to an object (the shared pointer) that no longer exists. If you cannot meet that requirement, pass a pointer to a new shared_ptr and delete it when the thread is done with it. (Or use boost:bind which works with shared pointers directly.)
As long as you're sure it's okay to assume ownership of the void* passed to you in f, that the void* does in fact refer to an A object, and you know the correct way to clean up, then you can just go ahead and use a smart pointer to assume ownership:
typedef boost::shared_ptr<A> A_SPtr;
void *f(void *var){
A_SPtr instance(static_cast<A*>(var));
}
Edit: It's not clear from the question, but some comments indicate that your actually trying to pass a smart pointer through a 'generic' interface that uses void*. You do this the same way you'd do it for any type:
void *f(void *var){
A_SPtr *instance = static_cast<A_SPtr *>(var);
}
And you pass the pointer like:
A_SPtr a;
f(&a);
As with any pointer you must ensure that the object's lifetime is sufficient for the pointer to be valid when f receives it.
Related
I am working on wrapping a C++ library into a C bridge.
All objects, I’d like to maintain with shared_ptrs on the heap like:
void* makeFoo() {
return new shared_ptr<void>(shared_ptr::make_shared<Foo>());
}
Can I use a generic destroy like this:
void destroy(void* p) {
delete static_cast<shared_ptr<void>*> p;
}
Or is there a cleaner way?
The type of the argument to delete must match the actual type of the thing you're deleting (otherwise how would the right destructor be invoked, for example?), or at least be a base type in a polymorphic hierarchy so the destructor can be found virtually ([expr.delete]/3).
So, no, you can't do that.
There are a two things at play here:
When you call new SomeType() ... then you need to call delete pointer where pointer has type SomeType * and points to the object allocated by that new expression. There are extensions to this rule with regards to base classes, but inheritance is not involved here, so we'll leave it at that.
shared_ptr<Foo> manages not only the Foo object, but also a "deleter" which knows how to destruct the Foo object. When you construct one shared_ptr from another, then that deleter gets passed on. This allows for "type erasure":
shared_ptr<Foo> typed = make_shared<Foo>();
shared_ptr<void> erased = typed;
Here, erased does no longer have compile time information about the type of the object it points to (that information was "erased"), but still has runtime information (the deleter) about the type of the object.
So to make this work, you need to make sure that you don't violate point 1 above; you need to delete the same type which you allocated with new: a shared_ptr<void>. This shared_ptr<void> needs to be constructed from a shared_ptr<Foo> because then it has a deleter which knows how to destruct a Foo:
void* makeFoo() {
shared_ptr<Foo> with_type = make_shared<Foo>();
shared_ptr<void> type_erased = with_type; // Just for illustration, merge with line below!
return new shared_ptr<void>(type_erased);
}
void destroy(void * ptr) {
shared_ptr<void> * original_ptr = ptr;
delete original_ptr;
}
makeFoo returns a pointer to a shared_ptr<void>. Just with the type info stripped, i.e. as void *.
destroy assumes it is passed such a pointer. Its delete calls the destructor of shared_ptr<void>. Because the shared_ptr<void> has the deleter of the original shared_ptr<Foo>, it knows how to actually destruct the object (Foo).
Side note: OP's code changed quite a few times, but still has basic syntax errors. This is not valid C++!!
delete <shared_ptr<void>*> p;
No. There is no such "generic delete".
Alternative solution: You can insert the std::shared_ptr<void> into a map, using the address of the dynamic object as key. The deallocation function can erase the shared pointer from the map.
In my code I use a library that has a function store_pointer accepting a void* and saving it in memory. There is then another function retrieve_pointer() that returns this void * to me, I don't have control over this library so I can't change how the function behaves.
Now I need to pass a variable to this function and get the pointer back, I have the code set up as follows:
struct Task
{
int mId;
Task(int id ) :mId(id)
{
std::cout<<"Task::Constructor"<<std::endl;
}
~Task()
{
std::cout<<"Task::Destructor"<<std::endl;
}
};
std::unique_ptr<Task> taskPtr(new Task(23));
store_pointer(&taskPtr);
// do stuff that doesn't involve taskPtr
Task *new_taskPtr = reinterpret_cast<Task *>(retrieve_pointer());
// do stuff with new_taskPtr pointer
Right now this all works but I wonder if the *new_taskPtr pointer needs to be deleted or if the reinterpret_cast "restores" the pointer to a unique_ptr and so the memory will be deleted automatically when it goes out of scope/the program ends.
std::unique_ptr<Task> taskPtr(new Task(23));
When this variable goes out of scope, the dynamic allocation will be deleted. There is no need to, and you mustn't delete it yourself unless you call release on the unique pointer, which is the only way to transfer the ownership out of a unique pointer (besides transferring ownership to another unique pointer).
Any casts that you may do have no effect on this.
You are storing a reference to unique_ptr:
store_pointer(&taskPtr);
As long as you don’t move the taskPtr or don’t mess with its internal pointer you are safe and don’t need delete.
Note that if taskPtr goes out of scope earlier than the user you will have dangling reference.
I am running into some problems porting some code that uses smart pointers.
Old code..
shared_ptr<Foo> create_Foo();
Where Foo is internally created via a function
Foo* Foo::FooFactory;
So i understand that we are creating a Ptr to a C++ class/object and then passing that ptr to the shared Ptr object to create a shared ptr that holds a ptr to an object of the type Foo...
But what happens when i want to create a smart ptr to hold an object that is typdef'd as an object form a void*?
Eg.
typdef void* FOO_HANDLE
shared_ptr<FOO_HANDLE> create_foo();
With an internal factory func like
FOO_HANDLE FooFactory();
Basically i am confused about to declare and create the shared_ptr object with a the typedef FOO_HANDLE object, that is essentially a void*!
Also because the FOO_HANDLE is a ptr to a C object it gets destroyed via a destroy method ala,
FooDestory(FOO_HANDLE);
So i guess i also need to tell the smart_prt about the method to destory the object.
I am starting to think that using smart ptrs here is the wrong approach..
but thought i would ask here first...
james
A std::shared_ptr<void> can hold a void*. When you construct such a shared_ptr, you need to provide the deleter, which will be type-erased (and is hence not part of the shared_ptr type itself). You can do this:
shared_ptr<void> create_foo() {
return {FooFactory(), FooDestroy};
}
I'm in c++ and i'm writing a wrapper around a c library. The c library function i'm working with takes a type 'LDAPMessage **' as a parameter, where it will allocate the memory for you within the function. Normal usage looks like this:
LDAPMessage * msg;
c_lib_function(&msg); // allocates the memory for me
Now I want to use unique_ptr in this case, with a custom deleter. Assume my deleter 'LDAPMessageDeleter' exists and works in the following.
unique_ptr<LDAPMessage*, LDAPMessageDeleter> msg_ptr(new LDAPMessage*);
c_lib_function(msg_ptr.get());
Though this compiles for me, i'm getting a seg fault. Could this code be at fault here? Is this correct usage of unique_ptr?
It might be easier to do e.g.
LDAPMessage* msg;
c_lib_function(&msg);
// Now we have out pointer (hopefully)
std::unique_ptr<LDAPMessage, LDAPMessageDeleter> msg_ptr(msg);
Of course, the LDAPMessageDeleter have to call the proper function to free the memory (e.g. free is the memory was allocated with malloc).
The problem with the code you show in the question, is that you try to create a pointer to a pointer, but don't make that first-level pointer actually point anywhere.
What you are effectively doing in your code is this:
LDAPMessage** msg;
c_lib_function(msg);
What's happening in the C library, is that the pointer is passed "by reference". Since C doesn't actually have proper references, it's kind of emulated by passing pointers. And passing a "reference" to a pointer is done by using the address-operator to pass the address of the pointer (which then becomes a pointer to the pointer).
Someone in the SO chat developed code valuely like this that I can no longer find:
//ptrptr magic
#include <memory>
template<class T, class deleter>
class ptrptr_type {
public:
ptrptr_type(std::unique_ptr<T, deleter>& ptr)
: uptr(&ptr), tptr(ptr.get()) {}
~ptrptr_type() {if (uptr->get()!=tptr) uptr->reset(tptr);}
operator T**() {return &tptr;}
private:
std::unique_ptr<T, deleter>* uptr;
T* tptr;
};
template<class T, class D>
ptrptr_type<T,D> ptrptr(std::unique_ptr<T, D>& ptr) { return {ptr};}
And the usage of this ptrptr is quite simple:
std::unique_ptr<LDAPMessage, LDAPMessageDeleter> my_ptr; //can be null or initialized, whichever
c_lib_function(ptrptr(my_ptr)); //use ptrptr(my_ptr) whenever you need a T**
That's it. Real simple. http://coliru.stacked-crooked.com/a/644ed001ffd547ae
What happens is ptrptr(my_ptr) creates a temporary ptrptr_type on the stack, which takes the pointer from the unique_ptr. The ptrptr then exposes a pointer to it's internal pointer, which the C function can freely modify. Afterwards, the temporary ptrptr_type is destroyed, and its destructor puts the new value for the pointer back into the original unique_ptr.
This isn't correct usage of the pointer-to-pointer. The function takes a pointer to uninitialized pointer and fills it. In your first example, this is a local variable. If you want it to be managed by unique_ptr, it should still be a local, just contained within the unique_ptr object.
LDAPMessage * msg;
c_lib_function(&msg); // allocates the memory for me
std::unique_ptr< LDAPMessage, LDAPMessageDeleter > // This type contains a ptr
msg_ptr( msg ); // transfer ownership to C++
LDAPMessageDeleter should receive a LDAPMessage *, and pass it to the library to be released if necessary, otherwise pass to free().
struct Temp
{
CString one;
CString two;
};
class Foo
{
public:
Temp obj;
void somewhere();
}
void Foo::somewhere()
{
void* pData = static_cast<void*>(&obj);
OwnMethod(pData); // void OwnMethod(void*);
}
The question is:
Should I create obj on heap or this situation isn't dangerous (passing local class objects pointer)?
If OwnMethod(pData) stores the pointer somwhere for later use, that later use is not possible anymore, once the object on which Foo::somewhere() is called is destroyed.
If OwnMethod(pData) only access the pointed to data, you are safe.
The member variable will last as long as the Foo object, so the pointer will be valid during the call to OwnMethod.
If that function stores a copy of the pointer somewhere, and something else uses that pointer later, then there is a danger that it might be accessed after the Foo (and therefore the pointer's target) have been destroyed. There are various ways to prevent that; as you say, one is to dynamically allocate the object, and then transfer or share ownership when it's passed to OwnMethod. Smart pointers, such as std::unique_ptr and std::shared_ptr, are a very good way to track ownership of dynamic objects.
Wow, a lot of issues.
A complex object should't be passed to anything taking a void*.
Who wrote OwnMethod?
Why doesn't it take a pointer of type Foo*?
In fact why doesn't it take a reference of type Foo&?
If OwnMethod() may be required to accept objects of several different types then it should take a base class pointer or reference and use polymorphism.
However as far as the lifetime arguments go - obj will exist as long as the wrapping class does, so if the pointer is not used beyond the scope of OwnMethod this is ok. If OwnMethod causes the pointer to be stored elsewhere beyond Foo's lifetime then you have an issue, and maybe obj should be allocated on the heap. (And it might not even be appropriate for it to be a member of Foo at all.)