C++如何销毁进程
- 手机
- 2025-09-02 01:24:01

从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(); }这样将会得到一个