【c++】【Linux】【进程】线程终止/崩溃 会导致进程终止/崩溃 吗?

news2025/3/12 12:42:09

【c++】【Linux】【进程】线程终止/崩溃 会导致进程终止/崩溃 吗?

1.线程终止会导致进程终止吗?

在操作系统中,线程是进程的基本执行单元,一个进程可以包含一个或多个线程。

  • 当一个子线程终止时,进程并不会因此自动终止,其他线程(包括主线程)仍然会继续运行。
  • 主线程都终止时,进程才会结束。

1子线程先结束,主线程继续执行,进程不会终止

1.1使用detach(): 将子线程与主线程分离
#include <iostream>
#include <thread>
#include <chrono>

void worker() {
    std::cout << "子线程开始执行。" << std::endl;
    std::this_thread::sleep_for(std::chrono::seconds(2));  // 模拟一些工作
    std::cout << "子线程结束。" << std::endl;
}

int main() {
    std::cout << "主线程开始执行。" << std::endl;

    std::thread t(worker);  // 创建子线程
    t.detach();  // 将子线程与主线程分离,主线程不等待子线程

    std::cout << "主线程继续执行,不等待子线程。" << std::endl;
    std::this_thread::sleep_for(std::chrono::seconds(5));  // 主线程继续执行
    std::cout << "主线程结束。" << std::endl;

    return 0;
}
  1. List itemstd::thread t(worker): 这行代码创建了一个新的子线程,执行 worker 函数。
  2. t.detach(): 将子线程与主线程分离,使得主线程不会等待子线程完成。子线程将独立执行。
  3. std::this_thread::sleep_for(std::chrono::seconds(5)): 主线程继续执行,并且睡眠 5 秒,确保子线程有时间执行。
  4. 子线程在 2 秒后结束,主线程在 5 秒后结束。
    运行结果:
    在这里插入图片描述
  • 主线程和子线程各自独立运行,互不干扰。
  • 即使子线程先于主线程结束,主线程仍会继续执行,直到完成其自身的任务。
1.2不使用detach(): 将子线程与主线程分离
#include <iostream>
#include <thread>
#include <chrono>

void worker() {
    std::cout << "子线程开始执行。" << std::endl;
    std::this_thread::sleep_for(std::chrono::seconds(2));  // 模拟一些工作
    std::cout << "子线程结束。" << std::endl;
}

int main() {
    std::cout << "主线程开始执行。" << std::endl;

    std::thread t(worker);  // 创建子线程

    std::cout << "主线程继续执行,不等待子线程。" << std::endl;
    std::this_thread::sleep_for(std::chrono::seconds(5));  // 主线程继续执行
    std::cout << "主线程结束。" << std::endl;

    return 0;
}

运行结果:
程序抛出了一个异常,但是异常没有被正确处理,但是主线程继续执行
在这里插入图片描述

1.3 使用 join(): 主线程等待子线程结束
#include <iostream>
#include <thread>
#include <chrono>

void worker() {
    std::cout << "子线程开始执行。" << std::endl;
    std::this_thread::sleep_for(std::chrono::seconds(5));
    std::cout << "子线程结束。" << std::endl;
}

int main() {
    std::cout << "主线程开始执行。" << std::endl;

    std::thread t(worker);  // 创建子线程

    // 使用 join() 确保主线程等待子线程完成
    t.join();

    std::cout << "主线程结束。" << std::endl;

    return 0;
}

运行结果:
主线程等待子线程结束,整个进程再结束
在这里插入图片描述

2主线程先结束,其他线程被迫终止,进程也终止

#include <iostream>
#include <thread>
#include <chrono>

void worker() {
    std::cout << "子线程开始执行。" << std::endl;
    std::this_thread::sleep_for(std::chrono::seconds(10));  // 模拟一些工作
    std::cout << "子线程结束。" << std::endl;
}

int main() {
    std::cout << "主线程开始执行。" << std::endl;

    std::thread t(worker);  // 创建子线程

    std::this_thread::sleep_for(std::chrono::seconds(2));  // 主线程继续执行
    std::cout << "主线程结束。" << std::endl;

    return 0;
}


在这里插入图片描述

  • 主线程先于子线程结束,子线程被迫中止,进程也结束了

2.线程崩溃会导致进程崩溃吗?

  • 子线程崩溃不一定会导致进程崩溃,关键在于如何处理子线程中的错误和异常。

2.1子线程崩溃导致进程崩溃的情况

2.1.1子线程访问非法内存(进程崩溃)

(1)

#include <iostream>
#include <pthread.h>

void* thread_func(void* arg) {
    // 模拟非法内存访问
    int* ptr = nullptr;
    *ptr = 42;  // 触发崩溃
    return nullptr;
}

int main() {
    pthread_t thread;

    // 创建子线程
    if (pthread_create(&thread, nullptr, thread_func, nullptr) != 0) {
        std::cerr << "Failed to create thread." << std::endl;
        return 1;
    }

    pthread_join(thread, nullptr);  // 等待子线程结束

    std::cout << "Main thread continues running." << std::endl;

    return 0;
}

执行结果
在这里插入图片描述
子线程访问了一个空指针,导致了段错误(Segmentation fault),进程崩溃。
(2)

#include <iostream>
#include <thread>
#include <string>

void thread_func(char* str) {
    // 尝试修改只读字符串
    str[0] = 'X';  // 修改字符串的第一个字符
    std::cout << "Thread modified string: " << str << std::endl;
}

int main() {
     char * str = "Hello, World!";  // 常量字符串(只读数据)

    // 创建多个线程来修改该字符串
    std::thread t1(thread_func, std::ref(str));
    std::thread t2(thread_func, std::ref(str));

    t1.join();
    t2.join();

    return 0;
}

执行结果
在这里插入图片描述
子线程访问了无法被修改的常量区数据,导致了段错误(Segmentation fault),进程崩溃。

2.1.2 子线程抛出未捕获的异常(进程崩溃)

如果子线程抛出未捕获的异常,默认情况下会导致调用 std::terminate,从而导致进程崩溃。

#include <iostream>
#include <pthread.h>
#include <stdexcept>

void* thread_func(void* arg) {
    // 模拟子线程中的异常
    throw std::runtime_error("Child thread crashed!");
    return nullptr;
}

int main() {
    pthread_t thread;

    // 创建子线程
    if (pthread_create(&thread, nullptr, thread_func, nullptr) != 0) {
        std::cerr << "Failed to create thread." << std::endl;
        return 1;
    }

    pthread_join(thread, nullptr);  // 等待子线程结束

    std::cout << "Main thread continues running." << std::endl;

    return 0;
}

执行结果
在这里插入图片描述

  • 子线程崩溃而没有适当的处理,std::terminate 会导致进程崩溃
  • 子线程未捕获异常而触发了 std::terminate,导致整个进程崩溃,而不仅仅是子线程。
    这是因为,在多线程程序中,std::terminate 的行为会影响整个进程,即使子线程崩溃,主线程仍然会被中断并导致进程崩溃。

2.2子线程崩溃,但进程继续运行(捕获异常或通过错误处理)

2.2.1子线程异常被捕获,进程不崩溃
#include <iostream>
#include <pthread.h>
#include <stdexcept>

void* thread_func(void* arg) {
    try {
        // 模拟子线程中的异常
        throw std::runtime_error("Child thread crashed!");
    } catch (const std::exception& e) {
        std::cerr << "Caught exception in child thread: " << e.what() << std::endl;
    }
    return nullptr;
}

int main() {
    pthread_t thread;

    // 创建子线程
    if (pthread_create(&thread, nullptr, thread_func, nullptr) != 0) {
        std::cerr << "Failed to create thread." << std::endl;
        return 1;
    }

    pthread_join(thread, nullptr);  // 等待子线程结束

    std::cout << "Main thread continues running." << std::endl;

    return 0;
}

执行结果
在这里插入图片描述

2.2.2 子线程崩溃(但是通过分离线程,主线程继续执行)
#include <iostream>
#include <pthread.h>
#include <stdexcept>

void* thread_func(void* arg) {
    throw std::runtime_error("Child thread crashed!");
    return nullptr;
}

int main() {
    pthread_t thread;

    // 创建子线程
    if (pthread_create(&thread, nullptr, thread_func, nullptr) != 0) {
        std::cerr << "Failed to create thread." << std::endl;
        return 1;
    }

    pthread_detach(thread);  // 分离子线程,主线程继续执行

    std::cout << "Main thread continues running." << std::endl;

    return 0;
}

执行结果
在这里插入图片描述
子线程抛出异常,但因为子线程已经分离,主线程不会被阻塞,进程继续运行,主线程完成执行。

总结

子线程崩溃导致进程崩溃的情况: 如果子线程因为非法内存访问(如空指针解引用)或者未捕获的异常(导致 std::terminate),则进程会崩溃。
子线程崩溃但不导致进程崩溃: 如果子线程抛出异常且异常被捕获,或者使用了 pthread_detach 来分离子线程,主线程仍然能够继续执行,进程不会崩溃。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2299767.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

springcloud集成gateway

本篇文章只介绍gateway模块的搭建步骤&#xff0c;并无gateway详细介绍 gateway详解请查看&#xff1a;SpringCloudGateway官方文档详解 前置处理 父模块中已指定版本 不知道如何选择版本看这篇&#xff1a; 手把手教你梳理springcloud与springboot与springcloudalibaba的版本…

pandas(13 Caveats Gotchas和SQL比较)

前面内容&#xff1a;pandas(12 IO工具和稀松数据) 目录 一、Caveats警告 & Gotchas预见 1.1 在Pandas中使用if/Truth语句 1.2 位运算布尔 1.3 isin操作 1.4 重新索引reindex和 loc&iloc 使用注意事项 1.5 loc和iloc 二、Python Pandas 与SQL的比较 2.1 数…

Android的Activity生命周期知识点总结,详情

一. Activity生命周期 1.1 返回栈知识点 二. Activity状态 2.1 启动状态 2.2 运行状态 2.3 暂停状态 2.4 停止状态 2.5 销毁状态 三. Activity生存期 3.1 回调方法 3.2 生存期 四. 体验Activity的生命周期 五. Activity被回收办法 引言&#xff1a; 掌握Acti…

基于Python的Flask微博话题舆情分析可视化系统

2024数据 ✅️标价源码 远程部署加 20 ✅️爬虫可用 有六月数据 ✅️修复bug不会突然打不开网页 系统稳定 系统的功能如下: 1.数据的爬取 2.用户的登录注册 3.热词统计&#xff0c;舆情统计 4.文章统计分析 5.发布地址统计 6.评论统计 7.情感分类统计 编程语言&#xff1a;py…

【油漆面积——线段树,扫描线,不用pushdown的特例,pushup兼有cal的性质】

题目 分析 不用pushdown是因为&#xff1a; 对于modify&#xff0c;操作是互逆过程&#xff0c;因此不会存在向下结算的pushdown过程 对于query&#xff0c;操作始终针对最上层的tr[1]&#xff0c;也不需要pushdown 对于pushdown&#xff0c;一则是怕不结算就标记&#xff0c;会…

深度学习(1)-简单神经网络示例

我们来看一个神经网络的具体实例&#xff1a;使用Python的Keras库来学习手写数字分类。在这个例子中&#xff0c;我们要解决的问题是&#xff0c;将手写数字的灰度图像&#xff08;28像素28像素&#xff09;划分到10个类别中&#xff08;从0到9&#xff09;​。我们将使用MNIST…

硬件学习笔记--42 电磁兼容试验-6 传导差模电流干扰试验介绍

目录 电磁兼容试验-传导差模电流试验 1.试验目的 2.试验方法 3.判定依据及意义 电磁兼容试验-传导差模电流干扰试验 驻留时间是在规定频率下影响量施加的持续时间。被试设备&#xff08;EUT&#xff09;在经受扫频频带的电磁影响量或电磁干扰的情况下&#xff0c;在每个步进…

Shader示例 6: 卡渲基础 - 描边 + 着色

0 、获取原神模型&#xff1a; 【游戏开发实战】下载原神模型&#xff0c;PMX转FBX&#xff0c;导入到Unity中&#xff0c;卡通渲染&#xff0c;绑定人形动画&#xff08;附Demo工程&#xff09;-CSDN博客 《原神》公测视频征集计划 一、描边pass&#xff1a;Outline 1. …

Cherno C++ P55 宏

这篇文章我们讲一下C当中的宏。其实接触过大型项目的朋友可能都被诡异的宏折磨过。 宏是在预处理当中&#xff0c;通过文本替换的方式来实现一些操作&#xff0c;这样可以不用反复的输入代码&#xff0c;帮助我们实现自动化。至于预处理的过程&#xff0c;其实就是文本编辑&am…

(20)从strlen到strtok:解码C语言字符函数的“生存指南1”

❤个人主页&#xff1a;折枝寄北的博客 ❤专栏位置&#xff1a;简单入手C语言专栏 目录 前言1. 求字符串长度函数1.1 strlen 2. 长度不受限制的字符串函数2.1 strcpy2.2 strcat2.3 strcmp 3. 长度受限制的字符串函数3.1 strncpy3.2 strncat3.3 strncmp 4. 字符串查找函数4.1 st…

Mongodb数据管理

Mongodb数据管理 1.登录数据库&#xff0c;查看默认的库 [rootdb51~]# mongo> show databases; admin 0.000GB config 0.000GB local 0.000GB> use admin switched to db admin > show tables system.version > admin库&#xff1a;admin 是 MongoDB 的管理…

从短片到长片:王琦携《Mountain》续作迈向新高度

在王琦(Qi Wang)的带领下,广受关注的短片《Mountain》迎来了成长篇续作《Rite of the Mountain》。这一全新长片不仅是她从短片迈向长篇叙事的重要一步,更是一次大胆的艺术挑战。作为制片人的她,将继续以敏锐的视觉风格和深刻的叙事洞察,拓展《Mountain》所触及的情感深度,并构…

DeepSeek应用——与PyCharm的配套使用

目录 一、配置方法 二、使用方法 三、注意事项 1、插件市场无continue插件 2、无结果返回&#xff0c;且在本地模型报错 记录自己学习应用DeepSeek的过程&#xff0c;使用的是自己电脑本地部署的私有化蒸馏模型...... &#xff08;举一反三&#xff0c;这个不单单是可以用…

如何画产品功能图、结构图

功能图的类型 常见的功能图包括数据流图、用例图、活动图、状态图、类图、组件图、部署图等等&#xff0c;不同的应用场景和目标下&#xff0c;需要确定不同的功能图类型。 数据流图 用例图 状态图 类图 组件图 组件图是由软件系统、组件和组件之间的关系组成的图形&#xf…

标准输入输出流,面向对象,构造函数

标准输入输出流 为什么不直接用printf和scanf? 不能输入/输出C新增的内容 std C的一些标识符&#xff0c;都是定义在std这个名字空间下面cout 是什么&#xff1f; 1.是一个ostream对象 output stream:输出流使用 <<&#xff1a;输出流运算符 作用&#xff1a;将右边…

PowerBI 矩阵 列标题分组显示(两行列标题)

先看效果 数据表如下&#xff1a; 我们在powerbi里新建一个矩阵&#xff0c;然后如图加入字段&#xff1a; 我们就会得到这样的矩阵&#xff1a; 我们在“可视化”->“列”&#xff0c;上双击&#xff0c;输入空格&#xff0c;就能消除左上角的"类别"两字 同理修…

服务器部署DeepSeek,通过Ollama+open-webui部署

1. 安装ollama 1.1. linux 安装 Ollama是目前常用的AI模式部署的第三方工具&#xff0c;能一键部署deepSeek Ollama官方网址https://ollama.com/ 选择Download下载对应的服务版本 服务器选择Linux&#xff0c;下面是下载代码 curl -fsSL https://ollama.com/install.…

Ubuntu 连接 air pods

&#xff11;&#xff0e; sudo vim /etc/bluetooth/main.conf , 修改蓝牙模式为blder &#xff12;&#xff0e;sudo /etc/init.d/bluetooth restart, 重启蓝牙&#xff0c;即可连接成功

民用无人驾驶航空器操控员考试

1. 注册 民用无人驾驶航空器综合管理平台 (caac.gov.cn) 2. 选择 操控员资质 3. 安全操控理论培训 -> 在线视频培训 学习完后选择 【在线考试】 共 50道 单项 选择题&#xff0c;每选项3个&#xff0c;80分及格。 4. 查看 我的合格证 证书有效期2年

002 第一个python程序

编程语言 编程语言可以做的事情&#xff1a; 网站开发、软件 、游戏、APP、 小程序、 爬虫、 数据分析、脚本 第一个python程序 找到IDE图标pycharm 新建项目 选择项目路径 创建目录 新建python文件 输入代码 运行程序查看结果 print 介绍 print : 输出内容…