温馨提示×

linux c++异常处理怎么做

小樊
31
2026-09-17 06:41:42
栏目: 编程语言

在 Linux 下用 C++ 做异常处理,本质上就是使用 C++ 标准异常机制(try / catch / throw,再结合 Linux 特有的一些信号、系统调用错误处理方式。下面分层说明。


一、C++ 标准异常处理(最常用)

1. 基本用法

#include <iostream>
#include <stdexcept>

void foo(int x) {
    if (x < 0)
        throw std::invalid_argument("x must >= 0");
}

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

2. 常见标准异常(<stdexcept>

  • std::runtime_error
  • std::logic_error
  • std::out_of_range
  • std::invalid_argument

3. 自定义异常

class MyException : public std::runtime_error {
public:
    explicit MyException(const std::string& msg)
        : std::runtime_error(msg) {}
};

二、Linux 下需要注意的点

1. 编译参数(非常重要)

GCC / Clang 下:

g++ -std=c++17 -O2 main.cpp -o main

✅ 现代 GCC 默认开启异常
❌ 不要加 -fno-exceptions(除非你明确不用异常)

2. 异常与 errno

Linux 系统调用失败通常:

  • 返回 -1
  • 设置 errno

示例:

#include <cerrno>
#include <cstring>
#include <stdexcept>

int fd = open("file", O_RDONLY);
if (fd < 0)
    throw std::runtime_error(strerror(errno));

三、信号(SIGSEGV / SIGFPE)不能直接 catch

C++ try/catch 不能捕获 Linux 信号

正确做法:信号 → 转异常(高级用法)

#include <csignal>
#include <csetjmp>

jmp_buf env;

void handler(int) {
    longjmp(env, 1);
}

int main() {
    signal(SIGSEGV, handler);
    if (setjmp(env) == 0) {
        // 可能崩溃的代码
    } else {
        // 处理“异常”
    }
}

⚠️ 不推荐新手用,容易破坏程序状态
✅ 更推荐:

  • 避免空指针
  • 用 sanitizer 查问题

四、RAII(Linux C++ 异常处理核心)

Linux 下资源(文件、socket、锁)必须用 RAII:

#include <fstream>

void func() {
    std::ofstream f("a.txt");
    // 即使抛异常,f 也会自动关闭
}

或自定义:

class FileGuard {
    FILE* fp;
public:
    FileGuard(const char* name) {
        fp = fopen(name, "r");
        if (!fp) throw std::runtime_error("open failed");
    }
    ~FileGuard() { if (fp) fclose(fp); }
};

五、调试与排错工具(Linux 必备)

1. 查看未捕获异常

g++ -g main.cpp
./a.out
# 崩溃时用 gdb
gdb ./a.out core

2. 捕获所有未处理异常

#include <exception>

void myTerminate() {
    std::cerr << "Unhandled exception\n";
    abort();
}

int main() {
    std::set_terminate(myTerminate);
}

3. Sanitizer(强烈推荐)

g++ -fsanitize=address -g main.cpp

六、最佳实践总结

✅ 用 std::exception 派生异常
✅ 用 catch(const std::exception&)
✅ 用 RAII 管理资源
✅ 系统调用失败转异常
❌ 不要用异常代替逻辑判断
❌ 不要试图 catch SIGSEGV


如果你愿意,我可以:

  • 给你一个 Linux socket / 文件 / 线程 的完整异常示例
  • 或讲 异常在嵌入式 Linux 是否该用
  • 或对比 C 的 errno vs C++ 异常

你更想看哪一种?

0