c++

智能指针赋值给Void*问题

c++

Posted by YiMiTuMi on September 13, 2023

智能指针赋值给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 被提前释放了。