插件窝 干货文章 C++在Linux下的异常处理策略

C++在Linux下的异常处理策略

异常 std include 使用 55    来源:    2025-05-08

C++在Linux下的异常处理策略

基本异常处理机制

C++在Linux平台下使用标准的try-catch异常处理机制:

#include <iostream>
#include <stdexcept>

void riskyFunction() {
    throw std::runtime_error("Something went wrong");
}

int main() {
    try {
        riskyFunction();
    } catch (const std::exception& e) {
        std::cerr << "Caught exception: " << e.what() << std::endl;
        return 1;
    }
    return 0;
}

Linux特有的异常处理考虑

1. 信号与异常交互

Linux系统中信号可能中断程序执行,需要特殊处理:

#include <csignal>
#include <iostream>

void signalHandler(int signum) {
    std::cerr << "Interrupt signal (" << signum << ") received.\n";
    // 清理并退出
    exit(signum);
}

int main() {
    signal(SIGINT, signalHandler);

    try {
        // 主程序逻辑
    } catch (...) {
        std::cerr << "Unknown exception caught\n";
    }

    return 0;
}

2. 资源清理

Linux下需要特别注意文件描述符、内存映射等资源的清理:

#include <fcntl.h>
#include <unistd.h>
#include <iostream>

class FileHandle {
    int fd;
public:
    FileHandle(const char* path, int flags) : fd(open(path, flags)) {
        if (fd == -1) throw std::runtime_error("Failed to open file");
    }

    ~FileHandle() {
        if (fd != -1) close(fd);
    }

    // 其他方法...
};

void useFile() {
    FileHandle fh("example.txt", O_RDONLY);
    // 使用文件
    throw std::runtime_error("Simulated error");
}

int main() {
    try {
        useFile();
    } catch (const std::exception& e) {
        std::cerr << "Error: " << e.what() << std::endl;
    }
    return 0;
}

高级异常处理技术

1. 异常安全保证

  • 基本保证:发生异常后对象处于有效状态
  • 强保证:操作要么完全成功,要么完全回滚
  • 不抛保证:操作保证不抛出异常
class Transaction {
    std::vector<int> data;
public:
    void addValue(int value) {
        std::vector<int> tmp = data;  // 创建副本
        tmp.push_back(value);         // 修改副本

        // 如果这里抛出异常,原始数据不变
        std::swap(data, tmp);         // 无抛出的交换
    }
};

2. 自定义异常类型

#include <exception>
#include <string>

class LinuxSystemError : public std::runtime_error {
    int errno_value;
public:
    LinuxSystemError(const std::string& msg)
        : std::runtime_error(msg + ": " + strerror(errno)), 
          errno_value(errno) {}

    int getErrno() const { return errno_value; }
};

void linuxSystemCall() {
    if (some_system_call() == -1) {
        throw LinuxSystemError("System call failed");
    }
}

最佳实践

  1. 异常 vs 错误码

    • 使用异常处理程序逻辑错误
    • 对预期可能发生的错误(如文件不存在)考虑使用错误码
  2. 资源管理

    • 使用RAII(Resource Acquisition Is Initialization)模式
    • 智能指针(std::unique_ptr, std::shared_ptr)管理动态内存
  3. 异常规格

    • 避免使用动态异常规格(C++11已弃用)
    • 使用noexcept标记确实不会抛出异常的函数
  4. 多线程环境

    • 确保异常不会导致死锁
    • 使用std::exception_ptr跨线程传递异常
#include <future>
#include <iostream>

void worker() {
    throw std::runtime_error("Error in worker thread");
}

int main() {
    auto future = std::async(std::launch::async, worker);

    try {
        future.get();
    } catch (const std::exception& e) {
        std::cerr << "Caught exception from thread: " << e.what() << std::endl;
    }

    return 0;
}

调试与诊断

  1. 核心转储分析

    • 使用ulimit -c unlimited启用核心转储
    • 用gdb分析核心文件:gdb <program> core
  2. 堆栈跟踪

    • 使用backtrace函数获取调用堆栈
    • 示例实现:
#include <execinfo.h>
#include <iostream>
#include <cxxabi.h>

void printStackTrace() {
    void* array[50];
    size_t size = backtrace(array, 50);
    char** messages = backtrace_symbols(array, size);

    for (size_t i = 0; i < size; ++i) {
        // 解析函数名(需要demangle C++名称)
        std::cout << messages[i] << std::endl;
    }

    free(messages);
}

void foo() {
    printStackTrace();
}

通过合理使用这些异常处理策略,可以构建健壮的Linux C++应用程序,能够优雅地处理错误情况并保持系统稳定性。