一个奇怪的问题

paragenius 2011-12-27 08:56:02
我写了一个程序,运行在许多不同的机器,
有windows XP和windows 2000
共一百多台机器,
是mon_log、dlog、wlog是程序里记录日志的函数。

目前的问题:间或有几台机器,日志文件出现大量乱码,程序崩溃。
好像访问了非法内存了或者内存溢出死掉了。
代码如下:

static int adjust_log(FILE *fp, char *logname)
{
char name[256];
char next[256]; //for example: name="mon2.log", so next="mon3.log"
int i;
#define GET_LOGNAME(name, num) sprintf(name, "%s.%d", logname, num)

GET_LOGNAME(name, LOG_FILE_NUM-1);
if(access(name, 0) == 0) {
GET_LOGNAME(name, LOG_FILE_NUM);
remove(name);
}
for(i = LOG_FILE_NUM-1; i > 0; i--) {
GET_LOGNAME(name, i);
if(access(name, 0) == 0) {
GET_LOGNAME(next, i+1);
rename(name, next);
}
}
GET_LOGNAME(next, 1);
CopyFile(LOG_FILE, next, FALSE);
chsize(fileno(fp), 0);

return 0;
}


#define MAX_LINE_SIZE 512

void write_log(FILE *fp, char *name, int type, char *msg)
{
time_t ltime;
struct tm *today;
#define TIME_STR_SIZE 64
char date_str[TIME_STR_SIZE] = {0};
char time_str[TIME_STR_SIZE] = {0};
int size;
char *typestr;
int rc;
time(<ime);
today = localtime(<ime);
switch(type) {
case INFO_TYPE:
typestr = "INF";
break;
case WARNING_TYPE:
typestr = "WAR";
break;
case ERROR_TYPE:
typestr = "ERR";
break;
case FATAL_TYPE:
typestr = "FAT";
break;
default:
return;
}
if (fp != NULL)
{
size = filelength(fileno(fp));
/* 文件大小超过10M,清空重新开始 */
if(size > LOG_FILE_MAX_SIZE) {
adjust_log(fp, name);
}
if (today != NULL) {
rc = sprintf(date_str,"%04d/%02d/%02d",today->tm_year+1900,today->tm_mon+1,today->tm_mday);
sprintf(time_str,"%02d:%02d:%02d",today->tm_hour,today->tm_min,today->tm_sec);
}
date_str[TIME_STR_SIZE - 1] = '\0';
time_str[TIME_STR_SIZE - 1] = '\0';
fprintf(fp, "%s %s(%s): ", date_str, time_str, typestr);
fprintf(fp, "%s", msg);
fprintf(fp,"\n");
fflush(fp);
}
return;
}

void dlog(int type, const char *format, ...)
{
va_list ap;
FILE *fp;
char msg[MAX_LINE_SIZE];

fp = fopen(LOG_FILE, "a+");
if(NULL == fp) {
return;
}
va_start(ap, format);
_vsnprintf(msg, sizeof(msg)-1, format, ap);
msg[MAX_LINE_SIZE-1] = '\0';
va_end(ap);
write_log(fp, LOG_FILE, type, msg);
fclose(fp);
return;
}

void wlog(char *name, int type, const char *format, ...)
{
va_list ap;
FILE *fp;
char msg[MAX_LINE_SIZE];
fp = fopen(name, "a+");
if (NULL == fp) {
return;
}

va_start(ap, format);
_vsnprintf(msg, sizeof(msg)-1, format, ap);
msg[MAX_LINE_SIZE-1] = '\0';
va_end(ap);
write_log(fp, name, type, msg);

fclose(fp);
return;
}

void mon_log (int type, const char *format, ...)
{
va_list ap;
static FILE *fp;
static HANDLE hMutex;
char msg[MAX_LINE_SIZE];
if(hMutex == NULL) {
hMutex = CreateMutex(NULL, FALSE, NULL);
if (hMutex == NULL) {
printf("CreateMutex error: %d\n", GetLastError());
return;
}
}
WaitForSingleObject(hMutex, INFINITE);
if(NULL == fp) {
fp = fopen(LOG_FILE, "a+");
}
va_start(ap, format);
_vsnprintf(msg, sizeof(msg)-1, format, ap);
msg[MAX_LINE_SIZE-1] = '\0';
va_end(ap);
write_log(fp, LOG_FILE, type, msg);
ReleaseMutex(hMutex);

return;
}

...全文
160 6 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
6 条回复
切换为时间正序
请发表友善的回复…
发表回复
ko8086 2011-12-28
  • 打赏
  • 举报
回复
指针跑飞了,你测一下末端
paragenius 2011-12-28
  • 打赏
  • 举报
回复
忘了提一点,这是个多线程的程序。
问题的原因是:
我使用了CreateThread创建的线程。这种方式创建的线程,调用的C运行时库不是线程安全的。
应该改成_beginthread、_beginthreadex
paragenius 2011-12-28
  • 打赏
  • 举报
回复
原因找到了。
我的这个程序是多线程的,
我使用CreateThread创建的线程,这个方式创建的线程,C runtime lib不是线程安全的。
而我经常在linux写程序,用习惯了C库,不喜欢windows API,调用就大量调用C库中的函数。
结果就出问题了。

应该用_beginthread或者_beginthreadex创建多线程,如果你在线程中使用C库的话。
c_losed 2011-12-27
  • 打赏
  • 举报
回复
感觉是指针飞了
ouyh12345 2011-12-27
  • 打赏
  • 举报
回复
这样的情况,不好调试
试试崩溃后生成dump文件,windows下可以用crashrpt
breakpad可以用在windows和linux下
gqjjqg 2011-12-27
  • 打赏
  • 举报
回复
这种问题排查起来挺麻烦的,一般要从入口开始排查,这种具体的问题,一般人没有运行环境,也比较难了解具体情况,而且你也说是间或出现,估计和运行环境关系比较大,代码相信你也自己检查过了。

所以我的建议是:
1.检查出问题的时候输入参数是否所有机器上都是合法输入。
2.检查日志内容是否原本就是乱码,可能会有一些字符编码方式的问题。
3.检查是否多个进程抢占,导致输入先后交替造成乱码(dlog方法)。

----
CreateMutex 为什么在mon_log方法里,应该放初始化里吧?不然我多次调用mon_log,不是照样执行?

dlog方法里为什么没有互斥保证,除非你外部确保只有一个进程调用。
----
主要还是先定位问题所在:到底是代码问题还是环境问题。

70,023

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧