C 语言错误输出及日志

01 Jan 2024 2489 words 9 minutes BY-SA 4.0
develop c

不要重复造轮子。

– 佚名

错误表述

C 语言没有异常机制。

使用异常或状态

别的编程语言的函数类似 y = f(x), 如果运行会出错就抛出一个异常。

C 很多本来可以没有返回值的函数有返回值 status = f(x, &y): status 为 0 表示没有出错。

此类函数有:

使用哨兵值

比如有的编程语言 y = f(x) ,如果 yNone 就是出错,否则就是正确的结果。

C 中可以使用 y = f(x) 其中:

此类函数有:

一般地(笔者观察的规律):

错误处理

无封装

因为 strerr() 会返回所有 errno 的错误信息,所以可以:

#if 0
bin="$(basename "$0")" && bin="${bin%%.*}" && cc "$0" -o"$bin" && exec ./"$bin" "$@"
#endif
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define FILE_NAME "non_existent_file"

int main(int argc, char *argv[]) {
  FILE *fp = fopen(FILE_NAME, "r");
  if (fp == NULL) {
    fprintf(stderr, "%s: %s: %s\n", argv[0], FILE_NAME, strerror(errno));
    return EXIT_FAILURE;
  }

  return EXIT_SUCCESS;
}
$ chmod +x main.c
$ ./main.c
./main: non_existent_file: No such file or directory

fprintf() 明显可以封装一下。

第一次封装

stdio.h 提供封装好的 perror()

#if 0
bin="$(basename "$0")" && bin="${bin%%.*}" && cc "$0" -o"$bin" && exec ./"$bin" "$@"
#endif
#include <stdio.h>
#include <stdlib.h>

#define FILE_NAME "doesn't_exist_file"

int main(int argc, char *argv[]) {
  FILE *fp = fopen(FILE_NAME, "r");
  if (fp == NULL) {
    fprintf(stderr, "%s: ", argv[0]);
    perror(FILE_NAME);
    return EXIT_FAILURE;
  }
  return EXIT_SUCCESS;
}

第二次封装

如果不需要退出可以使用 perror() 。如果需要退出可以直接用 err()

#if 0
bin="$(basename "$0")" && bin="${bin%%.*}" && cc "$0" -o"$bin" && exec ./"$bin" "$@"
#endif
#include <stdio.h>
#include <stdlib.h>
#include <err.h>

#define FILE_NAME "doesn't_exist_file"

int main(int argc, char *argv[]) {
  FILE *fp = fopen(FILE_NAME, "r");
  if (fp == NULL)
    err(EXIT_FAILURE, FILE_NAME);

  return EXIT_SUCCESS;
}

不过需要注意 err.h 是 POSIX C 的头文件不是 ANSI C 的。

日志

我们的更多需求:

内核空间

linux/module.h 中的 printk("XXX") 的输入的第一个字符(不可见字符)用来表达等级 。如果第一个字符不是不可见字符,则使用默认的等级。 所以使用的时候经常 printk(LEVEL "XXX")

用户空间

POSIX C 的 syslog.h 中的 syslog(LEVEL, "XXX") 。默认不打印输出结果。日志的输出结果需要通过一个 syslogd 的守护进程记录。常见的 syslogd 包括:

https://user-images.githubusercontent.com/32936898/199681341-1c5cfa61-4411-4b67-b268-7cd87c5867bb.png https://user-images.githubusercontent.com/32936898/199681363-1094a0be-85ca-49cf-a410-19b3d7965120.png https://user-images.githubusercontent.com/32936898/199681368-c34c2be7-e0d8-43ea-8c2c-d3e865da6aeb.png