3.3 封装
为减少错误检查和处理代码的重复性,可对函数调用或错误输出进行封装。
封装具有错误返回值的函数
通常针对频繁调用的基础性系统函数,如内存和内核对象操作等。举例如下:
- pid_t Fork(void) //首字母大写,以区分系统函数fork()
- {
- pid_t pid;
- if((pid = fork())<0)
- {
- fprintf(stderr, "Fork error: %s\n", strerror(errno));
- exit(0);
- }
- return pid;
- }
Fork()函数出错退出时依赖系统清理资源。若还需清理其他资源(如已创建的临时文件),可增加一个负责清理的回调函数。
注意,并非所有系统函数都可封装,应根据具体业务逻辑确定。
封装错误输出
通常需要使用ISO C变长参数表特性。例如《Unix网络编程》中将输出至标准出错文件的代码封装如下:
- #include <stdarg.h>
- #include <syslog.h>
- #define HAVE_VSNPRINTF 1
- #define MAXLINE 4096 /* max text line length */
- int daemon_proc; /* set nonzero by daemon_init() */
- static void err_doit(int errnoflag, int level, const char * fmt, va_list ap)
- {
- int errno_save, n;
- char buf[MAXLINE + 1];
- errno_save = errno; /* Value caller might want printed. */
- #ifdef HAVE_VSNPRINTF
- vsnprintf(buf, MAXLINE, fmt, ap);
- #else
- vsprintf(buf, fmt, ap); /* This is not safe */
- #endif
- n = strlen(buf);
- if (errnoflag) {
- snprintf(buf + n, MAXLINE - n, ": %s", strerror(errno_save));
- }
- strcat(buf, "\n");
- if (daemon_proc) {
- syslog(level, buf);
- } else {
- fflush(stdout); /* In case stdout and stderr are the same */
- fputs(buf, stderr);
- fflush(stderr);
- }
- return;
- }
- void err_ret(const char * fmt, ...)
- {
- va_list ap;
- va_start(ap, fmt);
- err_doit(1, LOG_INFO, fmt, ap);
- va_end(ap);
- return;
- }
|