微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

C++11 Bug分析:std::thread用法不当引发的灾难

项目场景:

最近换了新工作,主要是进行android camera HAL层性能优化工作,发现某些过程可以提前多线程处理,就使用了c++11开始提供的std::thread进行Demo开发,开发完成后开始调试,果然第一次运行出故障了,camera直接闪退了,不用想,肯定是修改导致的了。


问题描述

使用std::thread进行多线程运行任务,导致camera直接闪退,因为公司项目保密,无法提供源码,这里提供一个简单的windows应用程序来复现问题:

源码:

#include <iostream>
#include <memory>
#include <thread>

using namespace std;

class ThreadTest 
{
private: 
	std::unique_ptr<std::thread> mptrThread;

public:
	ThreadTest();
	void ThreadBody();
	void CreateThread();
	void JoinThread();
	void DetachThread();

	~ThreadTest();
};

ThreadTest::ThreadTest() : mptrThread(nullptr) {}

ThreadTest::~ThreadTest()
{
	//DetachThread();
}

void ThreadTest::CreateThread()
{
	mptrThread = std::make_unique<std::thread>(&ThreadTest::ThreadBody, this);
	if (mptrThread == nullptr)
	{
		std::cout << "std::make_unique<std::thread> Failed!" << std::endl;
	}
}

void ThreadTest::JoinThread()
{
	if (mptrThread != nullptr && mptrThread->joinable())
	{
		mptrThread->join();
	}
}

void ThreadTest::DetachThread()
{
	if (mptrThread != nullptr && mptrThread->joinable())
	{
		mptrThread->detach();
		mptrThread = nullptr;
	}
}

void ThreadTest::ThreadBody()
{
	std::cout << "running thread..." << std::endl;
}

int main()
{
	{
		ThreadTest stObj;
		stObj.CreateThread();

		//stObj.JoinThread();
		//stObj.DetachThread();
	}

	system("pause");
	return 0;
}

上面示例程序执行结果:

在这里插入图片描述


原因分析:

本人公司项目中camera闪退是因为std::thread变量的声明周期结束时,调用std::thread::~thread()析构函数时,触发了内部的terminate()函数,导致camera进程闪退。
为什么在std::thread的析构函数会触发terminate()函数呢,通过仔细阅读std::thread的使用方法发现,创建std::thread对象后,如果没有调用对应的join()或者detach()函数,在其析构函数中就会触发terminate()函数,仔细核对代码发现,确实有未调用join()或者detach()函数的过程,进行简单修改后问题就解决了。


解决方案:

在std::thread对象析构前,根据应用场景调用对应的join()或者detach()函数就可以避免该问题发生,修改方法可以查看上面代码中注释掉的部分。
修正后的运行结果(没有出现crash窗口了):

在这里插入图片描述

原文地址:https://www.jb51.cc/wenti/3287017.html

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐