我有一个使用std::shared_ptr
作为参数的API库。
我想将这些API与pthreads一起使用。
我正在做的是:从shared_ptr获取原始指针,以便将其传递给pthread。
从原始的一个创建一个新的shared_ptr,然后从另一个线程调用我的API。
但是,当将原始指针转换回共享指针时,出现double free or corruption
错误。
这是我的代码
#include <memory>
#include <iostream>
#include <thread>
#include <pthread.h>
void* print_task(void* ptr)
{
int* val_raw = static_cast<int*>(ptr);
std::shared_ptr<int> val(val_raw);
// CALL MY API WHICH TAKES A SHARED_PTR AS ARGUMENT
std::cout<<"thread job done \n";
}
int main(int argc, char ** argv)
{
pthread_t thread;
std::shared_ptr<int> val = std::make_shared<int>(10);
pthread_create(&thread, nullptr, &print_task, static_cast<void *>(val.get()));
std::this_thread::sleep_for(std::chrono::seconds(5));
return 0;
}
我猜我在从共享指针到原始指针的所有转换中都做错了,因为使用std :: threads的相同代码(我可以直接传递shared_ptr)起作用。 但是,我需要设置线程优先级,因此我试图使用pthreads来实现。
您知道如何更改代码以便能够传递共享指针并在pthread中使用它吗?
答案 0 :(得分:1)
正如评论中已经提到的那样,问题在于通过原始的void指针传递了共享指针,因此我现在暂时忽略线程部分:
// this is what we have and what we want to pass to the given function
shared_ptr<some_type> sptr;
// function to somehow pass the shared pointer to
void function(void* ptr);
// As always, when passing anything that doesn't fit into
// the raw pointer, we need to do dynamic allocation:
void* arg = new shared_ptr<some_type>(sptr);
// we can now pass this to the function as intended:
function(arg);
// Note that we give up ownership of the dynamically allocated
// shared pointer instance. Hence, the called function must
// release that object again (it takes ownership). The function
// therefore starts like this:
void function(void* ptr)
{
// convert the typeless pointer to a typed pointer again
shared_ptr<some_type>* psptr = static_cast<shared_ptr<some_type>*>(ptr);
// move the content to a new, local instance
shared_ptr<some_type> sptr = *psptr;
// release the dynamically allocated shared pointer again
delete psptr;
/// ... code using sptr here ...
}
现在,尽管可以保证可以正常工作,但在某些情况下,这可能不是最佳解决方案:
答案 1 :(得分:0)
老实说,我认为这是一个棘手的小难题。您遇到的问题是,通过将原始指针传递给线程函数,您最终得到两个独立共享指针来管理同一对象,而不是两个 connected < / em>共享指针共享所有权。
因此,两者共享指针都试图将其删除。
您也遇到了一个令人讨厌的生存期问题,以避免将指针传递给共享指针本身,因为您不能保证共享指针不会超出范围在新线程将其复制之前。
我通过绕过从原始std::shared_ptr
创建的动态分配的{strong> second {strong}秒来确保共享指针的控制块将一直存在,直到新线程尝试复制为止它。
std::shared_ptr
当然,您现在在这里有一个#include <memory>
#include <iostream>
#include <thread>
#include <pthread.h>
void* print_task(void* ptr)
{
// obtain the shared pointer from the dynamically created one guarantees
// we will bee accessing a living control block preventing an
// end-of-lifetime catastrophe
std::shared_ptr<int> val = *static_cast<std::shared_ptr<int>*>(ptr);
// DON'T FORGET TO DELETE THIS!!!
// We had to allocate this dynamically to guarantee it lived until after
// it was used.
delete static_cast<std::shared_ptr<int>*>(ptr);
// CALL MY API WHICH TAKES A SHARED_PTR AS ARGUMENT
std::cout << "thread job done \n";
return nullptr;
}
int main()
{
pthread_t thread;
// create the shared resource. This MAY go out of scope
// before the new thread copies it (however unlikely you
// think that is).
std::shared_ptr<int> val = std::make_shared<int>(10);
// So instead of sending the shared pointer we create a NEW std::shared_ptr
// which will keep the shared pointer's control block alive even if the original
// shared pointer goes out of scope.
pthread_create(&thread, nullptr, &print_task,
static_cast<void*>(new std::shared_ptr<int>(val)));
// Do other time consuming thread stuff here.
std::this_thread::sleep_for(std::chrono::seconds(2));
// Tidy up.
void* ret = nullptr;
pthread_join(thread, &ret);
return 0;
}
/ new
对,但是您仍然可以在线程之间传递共享所有权回合。
我想您甚至可以通过临时 delete
采用传入的原始指针来摆脱该delete
。
std::unique_ptr