不同于Java的异常处理机制, 当你使用C更多的接触到是基于错误码的异常机制, 简单来说就是当调用的函数发生异常时, 程序不会跳转到一个统一处理异常的地方, 取而代之的是返回一个整型错误码。

可能会有小伙伴有疑问了, 以打开文件为例该函数定义如下所示

int open(const char *pathname, int flags);

如果打开文件成功, open函数会返回一个文件描述符(该值大于0), 如果失败则返回-1。对于开发者来说, 只知道文件打开失败了, 而却不知道具体原因, 实际上的原因可能是多种多样的, 如:

  • 文件不存在
  • 当前进程没有该文件的读写权限

那么该如何知道具体错误呢? 这就需要借助系统为我们提供的errno机制了。

errno

errno是一个定义在errno.h头文件的全局整型变量,表示当前发生的最后一个错误, 只需在代码中引用errno.h这个头文件边可以获取到这个值。

如以下demo所示, 我们尝试打开一个不存在的文件

#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <fcntl.h> int main() {
int fd;
fd = open("/test.log", O_RDONLY);
if (fd == -1) {
printf("open failed, errno: %d\n", errno);
}
return 0;
}

运行该程序, 输出如下所示:

open failed, errno: 2

可以看出,此时错误码为2, 怎么知道这个错误码代表什么意思呢?

有以下方式

moreutils

  1. 安装moreutils
apt install moreutils
  1. 运行errno 错误码查看具体的错误信息

可以验证, 错误码2表示当前文件或目录不存在,与我们的预期一致

perror

使用定义在stdio.h中的perror函数可以直接在标准输出上打印错误信息

该函数定义如下所示, 我们可以在错误信息前附加自己定义的错误信息。

void perror(const char *s);

Demo:

int main() {
int fd;
fd = open("/test.log", O_RDONLY);
if (fd == -1) {
perror("open failed");
}
return 0;
}

输出:

strerr

如果我们只需要获取错误码对应的文本以记录日志, 可以使用strerr函数, 该函数定义在string.h

Demo:

int main() {
int fd;
fd = open("/test.log", O_RDONLY);
if (fd == -1) {
char* err_msg = strerror(errno);
printf("%s\n", err_msg);
}
return 0;
}

输出

线程安全的吗?

相信对于并发问题比较敏感的同学已经意识到了一个问题:这errno是一个整型的全局变量, 那如果多个线程同时执行系统调用, 并且都因为不同的原因失败了, 会不会导致其他线程的错误信息全部被最后一个产生错误的线程给覆盖掉了? 以及会不会有线程安全问题呢?

实际上errno被定义为了线程局部变量, 概念同Java中的ThreadLocal, 即每个线程都会有自己的errno变量, 不同线程之间不会互相影响。

最新文章

  1. OpenCASCADE Job - Shoe Doctor
  2. Java注解详解
  3. little tips of painter.drawRect in Qt
  4. (转)IC验证概述
  5. Android重要控件———ListView
  6. Nginx模块fastcgi_cache的几个注意点
  7. SQL Server Logical/Physical Reads
  8. 文件/图片,批量上传【神器】--WebUploader
  9. openresty使用笔记(一)
  10. 关于vue 框架与后台框架的混合使用的尝试
  11. Android 内存暴减的秘密?!
  12. [LeetCode] Degree of an Array 数组的度
  13. http协议与https协议的前世今生
  14. JAVA同步锁机制 wait() notify() notifyAll()
  15. sqlserver2012 offset分页
  16. tab选项卡在鼠标经过时实现切换延迟
  17. HTML使用的几个小知识点
  18. MarkDown学习——基础用法
  19. 使用node.js + json-server + mock.js 搭建本地开发mock数据服务
  20. MDI窗体容器

热门文章

  1. Object of type type is not JSON serializable
  2. Selenium+Tesseract-OCR智能识别验证码爬取网页数据
  3. Redis之品鉴之旅(三)
  4. java 从零开始手写 RPC (01) 基于 websocket 实现
  5. 拥抱开源,共建生态 - 开源生态与效能提升专场 | CIF 精彩看点
  6. Serverless 在大规模数据处理的实践
  7. 一个关于MySQL指定编码实现的小坑
  8. Spring 框架学习
  9. 论文解读(MPNN)Neural Message Passing for Quantum Chemistry
  10. Java(32)File类的介绍