温馨提示×

linux c++错误处理怎么做

小樊
36
2026-09-11 01:05:39
栏目: 编程语言

在 Linux 下用 C/C++ 做“错误处理”,通常涉及系统调用错误、C 标准库错误、C++ 异常、以及业务逻辑错误几个方面。下面按常见、实用、推荐的方式来讲。


一、系统调用 / C 库函数错误(最常见)

1. errno + 返回值判断(传统 C 方式)

原则:

  • 函数返回 -1 / NULL 表示失败
  • 错误原因在 errno
  • <cerrno> / <errno.h>
#include <iostream>
#include <cstdio>
#include <cerrno>
#include <cstring>

FILE* fp = fopen("test.txt", "r");
if (!fp) {
    std::cerr << "open failed: " << strerror(errno) << std::endl;
}

2. perror() / strerror()

perror("fopen");
// fopen: No such file or directory

推荐:

  • perror:简单
  • strerror(errno):可拼日志

二、Linux 特有错误(系统调用)

1. errno 示例(open / read / write)

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

int fd = open("a.txt", O_RDONLY);
if (fd < 0) {
    std::cerr << "open error: " << errno << " " << strerror(errno) << std::endl;
}

2. errno 线程安全

  • errno线程局部变量
  • 多线程安全 ✅

三、C++ 推荐的错误处理方式

1. 异常(推荐用于“非正常错误”)

#include <stdexcept>
#include <iostream>

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 << "error: " << e.what() << std::endl;
    }
}

✅ 适合:

  • 初始化失败
  • 配置错误
  • 不可恢复错误

❌ 不适合:

  • 高频路径
  • 系统调用错误(建议先转异常)

2. 异常 + 系统调用封装

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

void check(int ret, const char* msg) {
    if (ret < 0)
        throw std::runtime_error(std::string(msg) + ": " + strerror(errno));
}

int fd = open("x", O_RDONLY);
check(fd, "open");

四、错误码返回(适合库 / 高性能)

1. enum / int 错误码

enum class Err {
    OK = 0,
    NOT_FOUND,
    PERMISSION
};

Err readFile() {
    return Err::NOT_FOUND;
}

✅ 适合:

  • 网络库
  • 嵌入式
  • 高性能服务

2. std::expected(C++23,未来趋势)

#include <expected>

std::expected<int, int> foo() {
    return std::unexpected(1);
}

五、日志 + 错误上下文(很重要)

1. 错误要“可定位”

std::cerr << "[ERROR] " << __FILE__ << ":" << __LINE__
          << " open failed: " << strerror(errno) << std::endl;

2. 推荐日志库

  • spdlog
  • glog
  • boost.log

六、信号处理(Linux 特有)

#include <signal.h>
#include <iostream>

void handler(int sig) {
    std::cerr << "signal: " << sig << std::endl;
}

signal(SIGSEGV, handler);

⚠️ 信号处理函数里不能做复杂操作


七、常见最佳实践(总结)

系统调用errno + 返回值
库接口:错误码 or 异常
程序结构:异常用于“意外”
日志必须带上下文
❌ 不要吞错误
❌ 不要用异常代替流程控制


如果你愿意,我可以:

  • 给你一个 Linux C++ 错误处理模板
  • 服务端 / 网络编程错误模型
  • systemd / daemon 错误处理
  • 对比 C vs C++ 错误处理风格

你现在是写什么类型的程序?

0