智能指针赋值给Void*
在线程函数传递参数的时候,多半传递的都是 Void* 类型,当我们把一个 shared_ptr(智能指针)创建线程传递参数的时候,会导致 shared_ptr的计数器并不会 +1,就会导致后续使用的时候,发现 shared_ptr 被提前释放了。
例子:
class SharedTemp
{
public:
SharedTemp(int x);
~SharedTemp();
int iA;
private:
};
SharedTemp::SharedTemp(int x)
{
iA = x;
}
SharedTemp::~SharedTemp()
{
}
unsigned int __stdcall TestShared(void* pParam)
{
std::shared_ptr<SharedTemp> pSharedTe = *static_cast<std::shared_ptr<SharedTemp> *>(pParam);
while (TRUE)
{
std::cout << pSharedTe->iA;
Sleep(1000);
}
return 0;
}
void TestFunction()
{
std::shared_ptr<SharedTemp> pShared = std::make_shared<SharedTemp>(6);
//把智能指针传给一个void*
HANDLE hFileFind = (HANDLE)_beginthreadex(NULL, 0, TestShared, &pShared, 0, NULL);
CloseHandle(hFileFind);
}
int main()
{
TestFunction(); //在作用域里创建一个智能指针
while (TRUE)
{
Sleep(1000);
}
}
上面的这个函数会崩,提示 TestShared 线程里 pSharedTe 的地址无法访问,因为已经被释放了。我们在 TestFunction 函数里创建了一个 shared_ptr,将它往线程传递参数时计数器并不会 +1,当 TestFunction 函数结束的时候 pSharedTe 就被释放了,所以线程中再使用的时候就会报错。
但是往函数通过 Void* 传递智能指针就不会报错
我们将上面的 TestFunction 函数改写一下直接调用 TestShared函数:
void TestFunction()
{
std::shared_ptr<SharedTemp> pShared = std::make_shared<SharedTemp>(6);
TestShared(&pShared);
}
这个样子程序就会正常执行。
修改通过线程传参崩溃问题
改一下 TestFunction 函数,我们让 shared_ptr 进入线程前计数器额外 +1 就好:
void TestFunction()
{
std::shared_ptr<SharedTemp> pShared = std::make_shared<SharedTemp>(6);
//在这里额外nwe一下shared_ptr使计数器+1
HANDLE hFileFind = (HANDLE)_beginthreadex(NULL, 0, TestShared, new std::shared_ptr<SharedTemp>(pShared), 0, NULL);
int iErroe = GetLastError();
CloseHandle(hFileFind);
}
只需要额外nwe一下shared_ptr使计数器+1,就不会导致 shared_ptr 被提前释放了。