在 C/C++ 编程中,错误信息的捕获和处理是保证程序健壮性的重要部分。错误通常通过函数的返回值或者全局变量 errno 来表示。为了方便调试和错误处理,C/C++ 提供了多种函数和方法来获取和输出错误信息。以下是 C/C++ 错误处理的常见方法及函数介绍:
errno 和 perror()errno**:errno 是一个全局变量,当系统调用或库函数失败时,它会被设置为一个错误代码。errno 是由操作系统在发生错误时设置的,每个错误代码代表特定类型的错误。
perror()**:perror() 用于打印基于 errno 错误码的错误信息。它将 errno 的值转换为对应的错误消息并输出。如果提供了自定义的前缀字符串,则会一起输出。
#include <stdio.h>
#include <errno.h>
#include <string.h>
int main() {
FILE *file = fopen("non_existent_file.txt", "r");
if (!file) {
perror("File opening failed");
}
return 0;
}输出:
File opening failed: No such file or directory在此例中,perror() 输出了一个由 errno 设置的错误信息,具体是“没有这样的文件或目录”。
strerror()strerror()**:strerror() 函数用于将 errno 错误代码转换为可读的字符串,返回与 errno 对应的错误消息的指针。可以在程序中直接调用它来获取详细的错误描述。#include <stdio.h>
#include <errno.h>
#include <string.h>
int main() {
FILE *file = fopen("non_existent_file.txt", "r");
if (!file) {
printf("Error: %s\n", strerror(errno));
}
return 0;
}输出:
Error: No such file or directoryperror() 和 strerror() 区别perror() 会自动将错误信息输出到标准错误流 stderr,并可以附带自定义的前缀。strerror() 返回一个指向错误信息的指针,可以在程序中自己控制输出。exit() 和 abort()exit()**:exit() 用于退出程序并返回一个指定的状态码。返回的状态码可以用来表示程序的执行状态,通常 0 表示成功,非零值表示错误。#include <stdio.h>
#include <stdlib.h>
int main() {
if (some_error_condition) {
fprintf(stderr, "An error occurred\n");
exit(1); // Exit with status 1 (error)
}
return 0;
}abort()**:abort() 用于立即终止程序,通常在程序遇到无法恢复的错误时使用。调用 abort() 后,程序会立即中止,并且返回一个未定义的错误状态。#include <stdlib.h>
#include <stdio.h>
int main() {
if (some_fatal_error) {
abort(); // Immediately terminate the program
}
return 0;
}assert()assert()**:assert() 是用于调试时的一个宏,检查条件表达式是否为真。如果条件不为真,程序会输出错误信息并调用 abort() 终止程序。assert() 主要用于开发和调试阶段,不应该用于生产代码。#include <assert.h>
#include <stdio.h>
int main() {
int x = 5;
assert(x == 10); // This will fail and abort the program
return 0;
}setjmp() 和 longjmp()setjmp()**:setjmp() 用于设置一个恢复点。如果程序在后续调用 longjmp() 时跳转到该恢复点,setjmp() 会返回一个非零值。longjmp()**:longjmp() 用于从 setjmp() 所在的地方跳转到程序的某个恢复点。它可以用于错误处理,但一般不推荐作为常规的错误处理机制。#include <setjmp.h>
#include <stdio.h>
jmp_buf env;
void error_recovery() {
printf("Error occurred, recovering...\n");
longjmp(env, 1); // Jump back to setjmp
}
int main() {
if (setjmp(env) != 0) {
printf("Recovered from error\n");
return 0;
}
error_recovery(); // Call this to simulate error
return 0;
}strerror_r()strerror_r()**:strerror_r() 是线程安全的 strerror() 版本,它将错误信息写入传入的缓冲区中。由于 strerror() 不是线程安全的(它使用静态缓冲区),所以在多线程程序中推荐使用 strerror_r()。#include <stdio.h>
#include <string.h>
#include <errno.h>
int main() {
char buf[256];
errno = ENOENT;
strerror_r(errno, buf, sizeof(buf));
printf("Error: %s\n", buf);
return 0;
}perror() 和 strerror() 适用场景perror()**:适用于错误发生时立即输出错误信息,通常与文件操作、系统调用等直接相关的错误。strerror()**:适用于在多个地方需要引用或自定义错误消息输出的场景,尤其在日志记录和调试时很有用。ENOMEM**:内存不足EAGAIN**:暂时不可用,通常表示资源忙或阻塞EINVAL**:无效参数EBADF**:无效的文件描述符EIO**:输入/输出错误EPERM**:操作不允许ENOENT**:没有文件或目录fopen()、open()**:文件打开错误,返回 NULL 或 -1,需要使用 errno 判断具体错误。socket()**:创建套接字时的错误。connect()、send()、recv()**:网络编程中的错误。C/C++ 提供了一系列强大的错误处理机制,包括全局变量 errno 和函数 perror()、strerror() 等来输出和捕获错误信息。通过合理地使用这些函数,可以有效地捕获并报告程序中的错误,帮助开发人员在调试和生产环境中定位问题。