Я думаю, что это немного сложная головоломка, если честно.Проблема, с которой вы столкнулись, заключается в том, что, передав необработанный указатель в функцию потока, вы получаете два независимых общих указателя, управляющих одним и тем же объектом вместо два подключенного общие указатели совместное использование владение.
Следовательно оба общие указатели пытаются удалить его.
У вас также есть неприятный проблема времени жизни , чтобы избежать, если вы передадите указатель на сам общий указатель, потому что вы не можете гарантировать, что общий указатель не выйдет из области видимости до того, как новый поток его скопирует.
Я получаю округлениечто при передаче секунды , динамически распределяемой std::shared_ptr
, созданной из исходного 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
путем принятия переданного в необработанном указателе временным 1034 * std::unique_ptr
.
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 = *std::unique_ptr<std::shared_ptr<int>>(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;
}