- 论坛徽章:
- 0
|
在网上找了一段代码
写了一个测试程序,出现我百思不得其解的问题。
代码:
log.h
- /* -------------------------------------------------------------------------
- * log.h
- * -------------------------------------------------------------------------
- */
- #ifndef __LOG_H
- #define __LOG_H
- #include <stdio.h>
- #include <semaphore.h>
- #define LOGLINE_MAX 1024
- typedef struct {
- int fd;
- sem_t sem;
- int flags;
- } log_t;
- #define DEBUG 1
- #define INFO 2
- #define WARN 3
- #define ERROR 4
- #define FATAL 5
- /*
- * Logs to the logfile using printf()-like format strings.
- *
- * log_t - The value you got back from a log_open() call.
- * level - can be one of: DEBUG, INFO, WARN, ERROR, FATAL
- * fmt - is a printf()-like format string, followed by the parameters.
- *
- * Returns 0 on success, or -1 on failure.
- */
- int lprintf( log_t *log, unsigned int level, char *fmt, ... );
- #define LOG_TRUNC 1<<0
- #define LOG_NODATE 1<<1
- #define LOG_NOLF 1<<2
- #define LOG_NOLVL 1<<3
- #define LOG_DEBUG 1<<4
- #define LOG_STDERR 1<<5
- #define LOG_NOTID 1<<6
- /*
- * Initializes the logfile to be written to with fprintf().
- *
- * fname - The name of the logfile to write to
- * flags - The bitwise 'or' of zero or more of the following flags:
- * LOG_TRUNC - Truncates the logfile on opening
- * LOG_NODATE - Omits the date from each line of the log
- * LOG_NOLF - Keeps from inserting a trailing '\n' when you don't.
- * LOG_NOLVL - Keeps from inserting a log level indicator.
- * LOG_STDERR - Sends log data to stderr as well as to the log.
- * (this not implemented yet)
- *
- * Returns NULL on failure, and a valid log_t (value > 0) on success.
- */
- log_t *log_open( char *fname, int flags );
- /*
- * Closes a logfile when it's no longer needed
- *
- * log - The log_t corresponding to the log you want to close
- */
- void log_close( log_t *log );
- #endif
复制代码
log.c
- /* -------------------------------------------------------------------------
- * log.c - htun logging functions
- * -------------------------------------------------------------------------
- */
- #include <stdio.h>
- #include <unistd.h>
- #include <semaphore.h>
- #include <stdarg.h>
- #include <stdlib.h>
- #include <string.h>
- #include <errno.h>
- #include <time.h>
- #include <pthread.h>
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <fcntl.h>
- #include "log.h"
- /* Allows printf()-like interface to file descriptors without the
- * complications that arise from mixing stdio and low level calls
- * FIXME: Needs date and time before logfile entries.
- */
- int lprintf( log_t *log, unsigned int level, char *fmt, ... ) {
- int fd;
- int rc;
- va_list ap;
- time_t now;
- char date[50];
- static char line[LOGLINE_MAX];
- static char threadnum[10];
- int cnt;
- static char *levels[6] = { "[(bad)] ",
- "[debug] ",
- "[info ] ",
- "[warn ] ",
- "[error] ",
- "[fatal] " };
- if(!log) return -1;
- /* If this is debug info, and we're not logging it, return */
- if( !(log->flags&LOG_DEBUG) && level == DEBUG ) return 0;
- fd=log->fd;
- /* Prepare the date string 日期*/
- if( !(log->flags&LOG_NODATE) ) {
- now=time(NULL);
- strcpy(date,ctime(&now));
- date[strlen(date)-6]=' ';
- date[strlen(date)-5]='\0';
- }
- /*线程号*/
- if( !(log->flags&LOG_NOTID) ) {
- sprintf(threadnum, "(%lu) ", pthread_self());
- }
- cnt = snprintf(line, sizeof(line), "%s%s%s",
- log->flags&LOG_NODATE ? "" : date,
- log->flags&LOG_NOLVL ? "" :
- (level > FATAL ? levels[0] : levels[level]),
- log->flags&LOG_NOTID ? "" : threadnum);
- va_start(ap, fmt);
- vsnprintf(line+cnt, sizeof(line)-cnt, fmt, ap); /*如果输入的日志过长会自动截取*/
- va_end(ap);
- line[sizeof(line)-1] = '\0';
- if( !(log->flags&LOG_NOLF) ) {
- /*chomp(line);*/
- /*strcpy(line+strlen(line), "\n");*/
- }
- sem_wait(&log->sem); /*用信号实现同步*/
- rc = write(fd, line, strlen(line));
- sem_post(&log->sem);
- if( !rc ) errno = 0;
- return rc;
- }
- log_t *log_open( char *fname, int flags ) {
- log_t *log = malloc(sizeof(log_t));
- if(!log) {
- fprintf(stderr, "log_open: Unable to malloc()");
- goto log_open_a;
- }
- log->flags=flags;
- if( !strcmp(fname,"-") ) {
- log->fd = 2;
- } else {
- log->fd = open(fname, O_WRONLY|O_CREAT|O_NOCTTY |
- (flags&LOG_TRUNC ? O_TRUNC : O_APPEND) , 0666);
- }
- if( log->fd == -1 ) {
- fprintf(stderr, "log_open: Opening logfile %s: %s",
- fname, strerror(errno));
- goto log_open_b;
- }
- if( sem_init(&log->sem, 0, 1) == -1 ) {
- fprintf(stderr, "log_open: Could not initialize log semaphore.");
- goto log_open_c;
- }
- return log;
- log_open_c:
- close(log->fd);
- log_open_b:
- free(log);
- log_open_a:
- return NULL;
- }
- void log_close( log_t *log ) {
- sem_wait(&log->sem);
- sem_destroy(&log->sem);
- close(log->fd);
- free(log);
- return;
- }
复制代码
测试程序:
log_t.c
- #include <stdio.h>
- #include <stdlib.h>
- #include "log.h"
- log_t *log;
- int
- main(int argc, char **argv)
- {
- log = log_open("zzz.log", 0);
- lprintf(log, INFO, "test %d\n", 1000);
- lprintf(log, INFO, "test111111111111111111\n");
- log_close(log);
- return 0;
- }
复制代码
程序运行总是抱错:
Segmentation fault
gdb调试:
- (gdb) b main
- Breakpoint 1 at 0x8048bdc: file log_t.c, line 9.
- (gdb) r
- Starting program: /home/zang/186/thread_pool/zpksrc/log_t
- [Thread debugging using libthread_db enabled]
- [New Thread -1208314176 (LWP 7078)]
- [Switching to Thread -1208314176 (LWP 7078)]
- Breakpoint 1, main (argc=1, argv=0xbffdcbb4) at log_t.c:9
- 9 log = log_open("zpk.log", 0);
- (gdb) p &log
- $1 = (log_t **) 0x80495ac //log_open 之前全局指针的地址
- (gdb) p log
- $2 = (log_t *) 0x0 //log_open 之前全局指针的值
- (gdb) n
- 10 lprintf(log, INFO, "test %d\n", 1000);
- (gdb) p &log
- $3 = (log_t **) 0x80495ac //log_open 之后全局指针的地址
- (gdb) p log
- $4 = (log_t *) 0x828c008 //log_open 之后全局指针的值
- (gdb) n
- 11 lprintf(log, INFO, "test111111111111111111\n");
- (gdb) p &log
- $5 = (log_t **) 0x80495ac //lprintf 之后的全局指针的地址
- (gdb) p log
- $6 = (log_t *) 0x8280020 //lprintf 之后的全局指针的值,就是在这里指针的值竟然发生了改变.这里指针的值应该是不发生改变
- //的,大家看看为什么?就是因为指针值的改变,所以下面那个lprintf产生了段错误
- (gdb)
复制代码
大家看看究竟是怎么回事?
呵呵。。。
thanks |
|