在 Linux 下用 C/C++ 做“错误处理”,通常涉及系统调用错误、C 标准库错误、C++ 异常、以及业务逻辑错误几个方面。下面按常见、实用、推荐的方式来讲。
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;
}
perror() / strerror()perror("fopen");
// fopen: No such file or directory
推荐:
perror:简单strerror(errno):可拼日志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;
}
errno 线程安全errno 是 线程局部变量#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;
}
}
✅ 适合:
❌ 不适合:
#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");
enum / int 错误码enum class Err {
OK = 0,
NOT_FOUND,
PERMISSION
};
Err readFile() {
return Err::NOT_FOUND;
}
✅ 适合:
std::expected(C++23,未来趋势)#include <expected>
std::expected<int, int> foo() {
return std::unexpected(1);
}
std::cerr << "[ERROR] " << __FILE__ << ":" << __LINE__
<< " open failed: " << strerror(errno) << std::endl;
spdlogglogboost.log#include <signal.h>
#include <iostream>
void handler(int sig) {
std::cerr << "signal: " << sig << std::endl;
}
signal(SIGSEGV, handler);
⚠️ 信号处理函数里不能做复杂操作
✅ 系统调用:errno + 返回值
✅ 库接口:错误码 or 异常
✅ 程序结构:异常用于“意外”
✅ 日志必须带上下文
❌ 不要吞错误
❌ 不要用异常代替流程控制
如果你愿意,我可以:
你现在是写什么类型的程序?