strerror和erron参数函数的试用(经典)

strerror和erron参数函数的试用(经典)
2011年12月06日
  linux下错误的捕获:errno和strerror的使用
  经常在调用linux 系统api 的时候会出现一些错误,比方说使用open() write() creat()之类的函数有些时候会返回-1,也就是调用失败,这个时候往往需要知道失败的原因。这个时候使用errno这个全局变量就相当有用了。 在程序代码中包含 #include ,然后每次程序调用失败的时候,系统会自动用用错误代码填充errno这个全局变量,这样你只需要读errno这个全局变量就可以获得失败原因了。 例如:#include #include #include int main(void){int fd;extern int errno;if((fd = open("/dev/dsp",O_WRONLY)) Socket operation on non-socket */#define EDESTADDRREQ 89 /* Destination address required */#define EMSGSIZE 90 /* Message too long */#define EPROTOTYPE 91 /* Protocol wrong type for socket */#define ENOPROTOOPT 92 /* Protocol not available */#define EPROTONOSUPPORT 93 /* Protocol not supported */#define ESOCKTNOSUPPORT 94 /* Socket type not supported */#define EOPNOTSUPP 95 /* Operation not supported on transport endpoint */#define EPFNOSUPPORT 96 /* Protocol family not supported */#define EAFNOSUPPORT 97 /* Address family not supported by protocol */#define EADDRINUSE 98 /* Address already in use */#define EADDRNOTAVAIL 99 /* Cannot assign requested address */#define ENETDOWN 100 /* Network is down */#define ENETUNREACH 101 /* Network is unreachable */#define ENETRESET 102 /* Network dropped connection because of reset */#define ECONNABORTED 103 /* Software caused connection abort */#define ECONNRESET 104 /* Connection reset by peer */#define ENOBUFS 105 /* No buffer space available */#define EISCONN 106 /* Transport endpoint is already connected */#define ENOTCONN 107 /* Transport endpoint is not connected */#define ESHUTDOWN 108 /* Cannot send after transport endpoint shutdown */#define ETOOMANYREFS 109 /* Too many references: cannot splice */#define ETIMEDOUT 110 /* Connection timed out */#define ECONNREFUSED 111 /* Connection refused */#define EHOSTDOWN 112 /* Host is down */#define EHOSTUNREACH 113 /* No route to host */#define EALREADY 114 /* Operation already in progress */#define EINPROGRESS 115 /* Operation now in progress */#define ESTALE 116 /* Stale NFS file handle */#define EUCLEAN 117 /* Structure needs cleaning */#define ENOTNAM 118 /* Not a XENIX named type file */#define ENAVAIL 119 /* No XENIX semaphores available */#define EISNAM 120 /* Is a named type file */#define EREMOTEIO 121 /* Remote I/O error */#define EDQUOT 122 /* Quota exceeded */#define ENOMEDIUM 123 /* No medium found */#define EMEDIUMTYPE 124 /* Wrong medium type */#endif同时也可以使用strerror()来自己翻译如:#include #include [b]#include [/b]int main(void){int fd;extern int errno;if((fd = open("/dev/dsp",O_WRONLY)) < 0){ printf("errno=%d\n",errno); char * mesg = strerror(errno); printf("Mesg:%s\n",mesg);} exit(0);}dsp设备忙的话将输出如下:[b]errno=16Mesg:Device or resource busy[/b]
<think>我们被要求解释strerror函数的使用方法。根据引用[1],我们知道strerror函数是标准C库中用于处理错误的函数,但它不是线程安全的。而strerror_r是线程安全版本。不过用户明确询问的是strerror函数strerror函数的作用是将错误号(通常保存在errno中)转换为对应的错误描述字符串。函数原型(在<string.h>中声明):```cchar*strerror(interrnum); ```参数:- errnum:错误号,通常就是errno的值(errno是全局变量,在<errno.h>中声明) 返回值: -返回一个指向错误描述字符串的指针。注意,这个字符串是静态分配的,所以它可能会被后续的strerror调用覆盖(因此它不是线程安全的)。 使用步骤:1.在调用可能设置errno的系统调用或库函数后,如果该函数返回错误(通常通过返回-1或NULL等),我们可以检查errno。 2.使用strerror(errno)获取错误描述字符串。3.可以将这个字符串打印出来(例如使用perror或fprintf等)。注意:由于strerror返回的字符串是静态分配的,所以在多线程环境中,应该使用线程安全的版本strerror_r。示例代码:```c#include<stdio.h>#include <string.h> #include<errno.h>#include <fcntl.h> intmain(){FILE *file= fopen("non_existent_file.txt", "r");if(file== NULL) {//使用strerror获取错误描述char *error_msg= strerror(errno);printf("Erroropening file: %s\n", error_msg);//或者直接使用perror,它内部会调用strerrorperror("fopen");}return0; }``` 在这个示例中,我们尝试打开一个不存在的文件,fopen会返回NULL并设置errno。然后我们使用strerror获取错误描述字符串并打印。同时,我们也展示了使用perror的简洁方式,它会在给定的字符串后面自动添加冒号空格,然后加上错误描述。 另外,引用[2]中的代码示例展示了使用perror的情况,但我们这里重点在strerror。 文档说明:-在Linux或Unix系统中,可以通过`manstrerror`命令查看手册页。-根据C标准,strerror函数会返回一个指向字符串的指针,该字符串的内容由实现定义。不同的错误号对应不同的字符串。注意事项: 1.不要修改strerror返回的字符串,因为它是只读的(在C标准中,修改该字符串会导致未定义行为)。2.在多线程环境中,使用strerror_r替代。 相关问题: 1. strerrorperror有什么区别? 2.在多线程程序中如何处理错误信息? 3.如何自定义错误消息?</think>### `strerror` 函数使用指南 `strerror` 是标准 C 库中用于将错误号转换为可读错误描述的函数(定义在 `<string.h>` 头文件中)。它通过错误号(通常是 `errno` 的值)返回对应的错误描述字符串。 #### 函数原型 ```c char *strerror(int errnum); ``` - **参数** `errnum`:错误号(通常来自 `errno`) - **返回值**:指向错误描述字符串的静态缓冲区指针 --- ### 使用示例 ```c #include <stdio.h> #include <string.h> #include <errno.h> #include <fcntl.h> // 文件操作头文件 #include <unistd.h> // POSIX API int main() { // 尝试打开不存在的文件 int fd = open("non_existent_file.txt", O_RDONLY); if (fd == -1) { // 获取当前错误号 int error_code = errno; // 使用strerror转换错误号 char *error_msg = strerror(error_code); printf("错误号: %d\n", error_code); printf("错误描述: %s\n", error_msg); /* 等效的简洁写法: printf("错误: %s\n", strerror(errno)); */ } return 0; } ``` #### 输出示例: ``` 错误号: 2 错误描述: No such file or directory ``` --- ### 关键特性说明 1. **线程安全性问题** `strerror` 返回指向**静态内存**的指针,多线程中可能被覆盖: ```c // 线程不安全的用法 printf("Error 1: %s", strerror(EACCES)); printf("Error 2: %s", strerror(ENOENT)); // 可能覆盖前一个结果 ``` **解决方案**:多线程环境使用线程安全的 `strerror_r`(POSIX 标准) 2. **与 `perror` 的区别** - `strerror` 只返回错误字符串 - `perror` 自动附加用户消息并输出到 `stderr`: ```c perror("文件打开失败"); // 输出: 文件打开失败: No such file or directory ``` 3. **常见错误号常量**(`<errno.h>` 定义) | 错误号 | 描述 | |--------------|-----------------------| | `EACCES` | 权限不足 | | `ENOENT` | 文件/目录不存在 | | `EBUSY` | 设备或资源忙 | | `EINVAL` | 无效参数 | | `ENOMEM` | 内存不足 | --- ### 实际应用场景 ```c #include <stdio.h> #include <string.h> #include <errno.h> void safe_file_open(const char *filename) { FILE *fp = fopen(filename, "r"); if (!fp) { fprintf(stderr, "[%s] 打开失败: %s\n", filename, strerror(errno)); return; } // 文件操作... fclose(fp); } int main() { safe_file_open("/root/protected.txt"); // 触发EACCES safe_file_open("missing.txt"); // 触发ENOENT return 0; } ``` **输出**: ``` [/root/protected.txt] 打开失败: Permission denied [missing.txt] 打开失败: No such file or directory ``` --- ### 注意事项 1. **及时捕获错误** 系统调用后**立即**检查 `errno`,其他函数可能覆盖其值 2. **不可修改返回值** 返回的字符串是只读的,修改会导致未定义行为: ```c // 错误用法 ❌ strerror(EINVAL)[0] = 'X'; ``` 3. **跨平台差异** 不同系统可能有额外错误号(Windows 错误号与 POSIX 不同) --- ### 替代方案推荐 | 场景 | 推荐方案 | |---------------------|-------------------| | 单线程程序 | `strerror` | | 多线程程序 | `strerror_r` [^1] | | 快速输出错误 | `perror` | | C++ 环境 | `std::strerror` |
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值