MST

星途 面试题库

面试题:C++中如何通过RAII机制避免线程崩溃影响进程

在C++中,简述RAII(Resource Acquisition Is Initialization)机制的原理,并举例说明如何利用RAII来确保在线程崩溃时不会导致进程退出,例如在管理动态分配内存或文件句柄等资源的场景下。
25.2万 热度难度
编程语言C++

知识考点

AI 面试

面试题答案

一键面试

RAII原理

RAII(Resource Acquisition Is Initialization)机制核心在于将资源获取和对象生命周期绑定。当对象被创建(初始化)时,获取所需资源;当对象被销毁(析构)时,释放所获取的资源。这利用了C++中栈对象自动管理生命周期的特性,避免了手动管理资源时容易出现的资源泄漏等问题。

利用RAII确保线程崩溃不导致进程退出

1. 管理动态分配内存

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

class MemoryRAII {
public:
    MemoryRAII(size_t size) : data(new int[size]) {
        std::cout << "Memory allocated" << std::endl;
    }
    ~MemoryRAII() {
        delete[] data;
        std::cout << "Memory deallocated" << std::endl;
    }
private:
    int* data;
};

void threadFunction() {
    MemoryRAII mem(10);
    // 模拟线程崩溃
    throw std::runtime_error("Thread crashed"); 
}

int main() {
    try {
        std::thread t(threadFunction);
        t.join();
    } catch (const std::exception& e) {
        std::cerr << "Caught exception: " << e.what() << std::endl;
        // 进程不会退出,因为MemoryRAII对象在栈上,异常抛出时会自动析构释放内存
    }
    return 0;
}

2. 管理文件句柄

#include <iostream>
#include <thread>
#include <fstream>

class FileRAII {
public:
    FileRAII(const std::string& filename) : file(filename) {
        if (!file.is_open()) {
            throw std::runtime_error("Failed to open file");
        }
        std::cout << "File opened" << std::endl;
    }
    ~FileRAII() {
        if (file.is_open()) {
            file.close();
            std::cout << "File closed" << std::endl;
        }
    }
private:
    std::ofstream file;
};

void threadFunction2() {
    FileRAII file("test.txt");
    // 模拟线程崩溃
    throw std::runtime_error("Thread crashed"); 
}

int main2() {
    try {
        std::thread t(threadFunction2);
        t.join();
    } catch (const std::exception& e) {
        std::cerr << "Caught exception: " << e.what() << std::endl;
        // 进程不会退出,因为FileRAII对象在栈上,异常抛出时会自动析构关闭文件
    }
    return 0;
}

在上述代码中,无论是动态分配内存还是文件句柄,都通过RAII机制在对象生命周期结束时自动释放资源。即使线程发生崩溃,由于栈上对象的自动析构,资源能够得到正确释放,从而避免因资源泄漏等问题导致进程退出。