MST

星途 面试题库

面试题:C++中线程崩溃导致进程终止常见的资源未释放情况

在C++中,假设存在一个线程,在线程函数里申请了堆内存和打开了文件,若线程崩溃导致进程终止,可能存在哪些资源未释放的情况?请分别从内存资源和文件资源等方面进行说明,并简述如何避免这些资源泄漏。
40.6万 热度难度
编程语言C++

知识考点

AI 面试

面试题答案

一键面试

资源未释放情况

  1. 内存资源:在线程函数里申请的堆内存(如使用new关键字或malloc函数申请的内存),若线程崩溃,这部分堆内存无法被正常释放,导致内存泄漏。因为线程异常终止时,不会自动调用delete(对应new)或free(对应malloc)来释放申请的内存。
  2. 文件资源:打开的文件描述符不会自动关闭。文件处于打开状态,但程序已崩溃,没有机会执行关闭文件的操作(如fcloseclose函数),这会导致文件资源未释放。在某些系统中,可能会影响其他程序对该文件的访问,并且可能导致文件系统资源占用。

避免资源泄漏的方法

  1. 内存资源
    • 智能指针:使用C++ 标准库中的智能指针(std::unique_ptrstd::shared_ptr等)来管理堆内存。智能指针利用RAII(Resource Acquisition Is Initialization)机制,在对象的构造函数中获取资源(如申请内存),在析构函数中释放资源(如调用delete)。当智能指针超出作用域或线程正常结束时,会自动释放其所管理的内存。例如:
#include <memory>

void threadFunction() {
    std::unique_ptr<int> ptr(new int(10));
    // 线程函数其他代码
}
- **容器**:对于动态数组,可以使用`std::vector`等容器。容器同样基于RAII机制,会在其析构时自动释放内部元素所占用的内存。

2. 文件资源: - RAII封装:可以将文件操作封装在一个类中,利用RAII机制管理文件资源。在类的构造函数中打开文件,在析构函数中关闭文件。例如:

#include <iostream>
#include <fstream>

class FileGuard {
public:
    FileGuard(const std::string& filename) : file(filename) {
        if (!file) {
            throw std::runtime_error("Failed to open file");
        }
    }
    ~FileGuard() {
        file.close();
    }
    std::ofstream& getFile() {
        return file;
    }
private:
    std::ofstream file;
};

void threadFunction() {
    try {
        FileGuard fileGuard("test.txt");
        std::ofstream& file = fileGuard.getFile();
        file << "Some data";
    } catch (const std::exception& e) {
        std::cerr << "Exception: " << e.what() << std::endl;
    }
}
- **RAII 工具类**:C++ 标准库中也有`std::ifstream`、`std::ofstream`等文件流类,它们在析构时会自动关闭文件,所以在使用文件流对象时,只要确保它们在合适的作用域内正常析构,就能避免文件资源泄漏。