您的位置:首页 > 文旅 > 美景 > 赣州专业做网站_网站建站模版_惠州seo公司_一站式网站设计

赣州专业做网站_网站建站模版_惠州seo公司_一站式网站设计

2025/7/16 15:08:55 来源:https://blog.csdn.net/weixin_43868793/article/details/145712403  浏览:    关键词:赣州专业做网站_网站建站模版_惠州seo公司_一站式网站设计
赣州专业做网站_网站建站模版_惠州seo公司_一站式网站设计

从C++11开始,C++STL开始支持线程,
先看一个C++11 thread的例子

#include "stdafx.h"
#include <thread>
#include <chrono>
#include <iostream>
#include <functional>
#include <string>bool isRunning = true;
std::thread* tptr;
uint8_t* byte_ptr;
constexpr size_t kLen = 10;static void ShowMem(uint8_t* p, const size_t size = kLen)
{for (size_t i = 0; i < kLen; ++i){printf("%02x", p[i]);}printf("\n");
}void thread_func()
{static int i = 0;while (isRunning){std::this_thread::sleep_for(std::chrono::seconds(1));}std::cout << "thread_func finished" << std::endl;
}void Shell_Thread()
{std::string input;while (1){std::cin >> input;if (input == "exit"){exit(EXIT_SUCCESS);}if (input == "showmem"){ShowMem(byte_ptr, sizeof(std::thread));continue;}if (input == "release"){delete tptr;continue;}}
}int main()
{do {std::thread t(Shell_Thread); t.detach();} while (0);tptr = new std::thread(thread_func);tptr->detach();byte_ptr = reinterpret_cast<uint8_t*>(tptr);while (1){std::this_thread::sleep_for(std::chrono::milliseconds(1));}
}

在windows平台编译成debug版本,然后运行
先查看任务管理器
在这里插入图片描述

线程数是3
main函数一个主线程,Shell_Thread,thread_func 分别一个线程,总共3个线程

在控制台输入release 回车,然后输入showmem回车

release
showmem
dddddddddddddddddddd

可以看到输出dddd...
window平台,debug模式下free掉的内存会被系统填充成0xdd
销毁了线程并且windows也没有报错。
在任务管理器下面可以看到
在这里插入图片描述

tptr 所指向的thread对象销毁了,但thread_func 这个函数仍然在系统中运行。

现在将if (input == "release")分支下delete tptr;这一句换成isRunning = false;
重复上面执行一下可以看到

showmem
0000000000000000fdfd
release
thread_func finished
showmem
0000000000000000fdfd

在这里插入图片描述
线程数变成了2,但是tptr指向的内存没被free,内存泄露了。
std::cout << "thread_func finished" << std::endl; 这个语句后面加上一句delete tptr可以解决问题,但明显不会是一个好的方式。
需要自行包装一下Thread,在线程运行结束后自我销毁,或者由第三个对象在判断线程运行结束后再销毁线程对象。


现在看Qt下面一个多线程的例子

#include <QtCore/QCoreApplication>
#include <QThread>
#include <QDebug>
#include <iostream>class MyWrap
{
public:explicit MyWrap();virtual ~MyWrap();bool isRunning;QThread* t;
};class MyThread : public QThread {
public:explicit MyThread(MyWrap*);void run() Q_DECL_OVERRIDE;MyWrap* m_wrap;
};class MyShell : public QThread {
public:void run() Q_DECL_OVERRIDE;
};MyWrap *wrap_ptr;
QThread *tptr;
uint8_t* byte_ptr;
constexpr size_t kLen = 10;static void ShowMem(uint8_t* p, const size_t size = kLen)
{QString str;for (size_t i = 0; i < kLen; ++i){str += QString::number(p[i], 16);}qDebug() << str;
}int main(int argc, char *argv[])
{QCoreApplication a(argc, argv);do {QThread *shell = new MyShell();shell->start();} while (0);wrap_ptr = new MyWrap();tptr = wrap_ptr->t;byte_ptr = reinterpret_cast<uint8_t*>(tptr);tptr->start();return a.exec();
}void MyShell::run()
{std::string input;while (1){std::cin >> input;if (input == "exit"){QCoreApplication::exit(0);return;}if (input == "showmem"){ShowMem(byte_ptr, sizeof(MyThread));continue;}if (input == "release"){delete wrap_ptr;continue;}}
}MyThread::MyThread(MyWrap* wrap):QThread(),m_wrap(wrap)
{}void MyThread::run()
{while (m_wrap->isRunning){QThread::sleep(1);}qDebug() << __FUNCTION__ << " end";this->deleteLater();
}MyWrap::MyWrap(): isRunning(true)
{this->t = new MyThread(this);this->t->start();
}MyWrap::~MyWrap()
{isRunning = false;}

在上面例子中把m_wrap->isRunning换成一个全局的变量,程序可以按照预期的方向运行。

将MyWrap与MyThread修改成如下

MyWrap::~MyWrap()
{isRunning = false;this->t->quit();this->t->wait();delete this->t;
}void MyThread::run()
{while (m_wrap->isRunning){QThread::sleep(1);}qDebug() << __FUNCTION__ << " end";
}

程序也会如期运行。
但MyThread::run中执行太多耗时操作,而MyWrap是界面的操作,将会导致界面长时间卡顿。

将MyWrap与MyThread修改成如下

MyWrap::~MyWrap()
{this->t->requestInterruption();
}void MyThread::run()
{while (!this->isInterruptionRequested()){if (IsBadReadPtr(m_wrap,sizeof(MyWrap))) { break; }// read m_wrap-> ....QThread::sleep(1);}qDebug() << __FUNCTION__ << " end";this->deleteLater();
}

这样将会优雅的结束线程并销毁线程。

千万不要像下面这样

MyWrap::~MyWrap()
{this->t->requestInterruption();this->t->deleteLater();
}

这样将会得到一个
在这里插入图片描述

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com