目录
在 C/C++ 编程中,错误信息的捕获和处理是保证程序健壮性的重要部分。错误通常通过函数的返回值或者全局变量 errno
来表示。为了方便调试和错误处理,C/C++ 提供了多种函数和方法来获取和输出错误信息。以下是 C/C++ 错误处理的常见方法及函数介绍:
1. 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
设置的错误信息,具体是“没有这样的文件或目录”。
2. 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 directory
3. perror()
和 strerror()
区别
perror()
会自动将错误信息输出到标准错误流stderr
,并可以附带自定义的前缀。strerror()
返回一个指向错误信息的指针,可以在程序中自己控制输出。
4. 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;
}
5. 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;
}
6. 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;
}
7. 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;
}
8. perror()
和 strerror()
适用场景
- **
perror()
**:适用于错误发生时立即输出错误信息,通常与文件操作、系统调用等直接相关的错误。 - **
strerror()
**:适用于在多个地方需要引用或自定义错误消息输出的场景,尤其在日志记录和调试时很有用。
常见的 C/C++ 错误信息和函数
常见的错误信息
- **
ENOMEM
**:内存不足 - **
EAGAIN
**:暂时不可用,通常表示资源忙或阻塞 - **
EINVAL
**:无效参数 - **
EBADF
**:无效的文件描述符 - **
EIO
**:输入/输出错误 - **
EPERM
**:操作不允许 - **
ENOENT
**:没有文件或目录
常见的函数
- **
fopen()
、open()
**:文件打开错误,返回NULL
或-1
,需要使用errno
判断具体错误。 - **
socket()
**:创建套接字时的错误。 - **
connect()
、send()
、recv()
**:网络编程中的错误。
总结
C/C++ 提供了一系列强大的错误处理机制,包括全局变量 errno
和函数 perror()
、strerror()
等来输出和捕获错误信息。通过合理地使用这些函数,可以有效地捕获并报告程序中的错误,帮助开发人员在调试和生产环境中定位问题。