代码结构优化策略
- 封装文件系统调用函数
- 创建一组自定义函数来封装标准的文件系统调用,例如
open
、read
、write
、close
等。在这些自定义函数中统一处理错误,这样在项目的其他部分调用这些函数时,就无需重复编写错误处理代码。
- 示例:
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
int myOpen(const char *pathname, int flags) {
int fd = open(pathname, flags);
if (fd == -1) {
perror("open");
exit(EXIT_FAILURE);
}
return fd;
}
- 模块化设计
- 将与文件系统操作相关的功能划分到独立的模块中,每个模块负责特定的文件系统任务,如文件读取模块、文件写入模块等。每个模块内部处理好自身的错误,并向调用者返回统一的错误标识,使得错误处理逻辑在模块内集中管理,提高代码的可维护性。
- 例如,文件读取模块可以定义如下接口:
// file_read.h
#ifndef FILE_READ_H
#define FILE_READ_H
#define READ_SUCCESS 0
#define READ_ERROR -1
int readFile(const char *filename, char *buffer, size_t size);
#endif
// file_read.c
#include <stdio.h>
#include <stdlib.h>
#include "file_read.h"
int readFile(const char *filename, char *buffer, size_t size) {
FILE *file = fopen(filename, "r");
if (file == NULL) {
perror("fopen");
return READ_ERROR;
}
size_t result = fread(buffer, 1, size, file);
if (result != size) {
perror("fread");
fclose(file);
return READ_ERROR;
}
fclose(file);
return READ_SUCCESS;
}
错误处理机制优化策略
- 使用全局错误变量
- 定义一个全局变量来记录最近发生的错误码,在封装的文件系统调用函数中更新该变量。调用者可以通过检查这个全局变量来了解错误详情,避免在每个调用点重复获取错误码。
- 示例:
#include <errno.h>
#include <stdio.h>
// 全局错误变量
int globalErrno = 0;
int myOpen(const char *pathname, int flags) {
int fd = open(pathname, flags);
if (fd == -1) {
globalErrno = errno;
perror("open");
return -1;
}
globalErrno = 0;
return fd;
}
- 错误码映射表
- 对于不同的文件系统调用错误码,建立一个映射表,将系统错误码映射为自定义的、更具描述性的错误码,使得错误处理逻辑可以基于这些更易理解的错误码进行。
- 示例:
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
// 自定义错误码
typedef enum {
ERR_OPEN_FAILED = 1,
ERR_READ_FAILED,
ERR_WRITE_FAILED,
ERR_CLOSE_FAILED
} CustomErrorCode;
// 错误码映射表
CustomErrorCode mapErrnoToCustomErrno(int errnum) {
switch (errnum) {
case ENOENT:
return ERR_OPEN_FAILED;
case EIO:
return ERR_READ_FAILED;
case EACCES:
return ERR_OPEN_FAILED;
// 其他错误码映射
default:
return ERR_OPEN_FAILED;
}
}
int myOpen(const char *pathname, int flags) {
int fd = open(pathname, flags);
if (fd == -1) {
CustomErrorCode customErr = mapErrnoToCustomErrno(errno);
switch (customErr) {
case ERR_OPEN_FAILED:
perror("open");
break;
// 其他自定义错误处理
}
return -1;
}
return fd;
}
- 错误日志记录
- 在错误处理过程中,将错误信息记录到日志文件中,包括错误发生的时间、调用的函数、错误码等详细信息。这有助于在调试和维护阶段快速定位问题。
- 示例:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <fcntl.h>
#include <unistd.h>
void logError(const char *funcName, int errnum) {
FILE *logFile = fopen("error.log", "a");
if (logFile == NULL) {
perror("fopen for log");
return;
}
time_t now;
time(&now);
struct tm *tm_info = localtime(&now);
char timeStr[26];
strftime(timeStr, 26, "%Y-%m-%d %H:%M:%S", tm_info);
fprintf(logFile, "[%s] Function: %s, Error number: %d, Error message: %s\n",
timeStr, funcName, errnum, strerror(errnum));
fclose(logFile);
}
int myOpen(const char *pathname, int flags) {
int fd = open(pathname, flags);
if (fd == -1) {
logError("myOpen", errno);
perror("open");
return -1;
}
return fd;
}