读书人

c++ 流在多线程下出现不可捕获的错误异

发布时间: 2012-02-10 21:27:41 作者: rapoo

c++ 流在多线程下出现不可捕获的异常错误,在 windows 和 linux 中都出现,
c++ 流在多线程下出现不可捕获的异常错误,在 windows 和 linux 中都出现,
就是在 需要转存日志的这一行 m_output->close(); 确实怪异,导致程序退出

//头文件 simplelog.h 内容
#ifndef _CSIMPLELOG_INCLUDE_
#define _CSIMPLELOG_INCLUDE_

#include <string>
#include <iostream>

class MyOSMutex;

class CSimpleLog
{
private:
//日志文件路径
std::string m_logname;
//写文件锁
MyOSMutex *m_mutex;
//日志文件指针
std::ofstream *m_output;
//写缓冲
const unsigned int BUFFSIZE;
char *m_buff;
//char m_buff[BUFFSIZE];
//文件尺寸 20M
int m_maxfilesize;
//sington唯一实例
static CSimpleLog * m_instance;
//转存文件
void inline Save();
//得到新文件名
void inline GetNewFileName(char *filename);
protected:
CSimpleLog();
public:
//初始化
void Initiate(const std::string &logname,int maxfilesize = 20);
//写日志内容
void Addlog(const char* fmt, ...);
//按 16 进制输出数据包
void AddHexlog(const unsigned char *buff,int len);
//得到唯一实例
static CSimpleLog& Instance();

~CSimpleLog(void);
};
#endif

//实现 simplelog.cpp 内容
#include "simplelog.h"
#include "myosmutex.h"
#include <stdio.h>
#include <fstream>
#include <iostream>
#include <string>
using namespace std;
#include <stdarg.h>

CSimpleLog * CSimpleLog::m_instance = 0;

CSimpleLog::CSimpleLog():m_mutex(0),
m_output(0),m_buff(0),BUFFSIZE(1024),
m_maxfilesize(1024 * 1024 * 20)
{
if(m_mutex == 0)
{
m_mutex = new MyOSMutex();
}

if(m_buff == 0)
{
m_buff = new char[1024];
}
}

CSimpleLog::~CSimpleLog(void)
{
if(m_output)
{
m_output->flush();
m_output->close();
delete m_output;
m_output = 0;
}

if(m_buff)
{
delete []m_buff;
m_buff = 0;
}

if(m_mutex)
{
delete m_mutex;
m_mutex = 0;
}

delete this;
}

void CSimpleLog::Initiate(const std::string &logname,int maxfilesize)
{
m_maxfilesize = maxfilesize * 1024 * 1024;
m_logname = logname;
size_t length = logname.length();
if(length >= 255 || length < 4)
{
return;
}

char filename[255];
GetNewFileName(filename);
if(m_output == 0)
{
m_output = new std::ofstream(filename,ios::out|ios::ate|ios::app);
}
}

//得到唯一实例
CSimpleLog& CSimpleLog::Instance()
{
for(;;)
{
if(m_instance == 0)
{
m_instance = new CSimpleLog();
}
if(m_instance)
{
break;
}
}
return *m_instance;
}

void CSimpleLog::Addlog(const char* fmt, ...)
{
static unsigned short lines = 0;
m_mutex->Lock();
va_list argptr;
//分析字符串的格式
va_start(argptr,fmt);
#ifdef WIN32
_vsnprintf(m_buff,BUFFSIZE,fmt,argptr);
#else
vsnprintf(m_buff,BUFFSIZE,fmt,argptr);
#endif
va_end(argptr);

//以添加的方式输出到文件
if(m_output)
{
//CDateTime dt;
//(*m_output)<<dt.LongDateTime()<<" "<<m_buff<<endl;
(*m_output)<<m_buff<<endl;

if(m_output->bad())
{
m_output->clear();
}

lines++;
if(lines > 1000)
{
lines = 0;
//m_output->flush();
Save();
}
}
m_mutex->Unlock();
}

void inline CSimpleLog::GetNewFileName(char *filename)
{
//最多存储 50 个日志文件
const int MAXIUMCOUNT = 50;
for(int i = 0;i < MAXIUMCOUNT;++i)
{
//char filename[255];
//文件索引
static unsigned int short fileindex = 0;
memset(filename,0,sizeof(filename));


sprintf(filename,"%s_%02d.log",m_logname.c_str(),++fileindex);
FILE* fp = fopen(filename,"r");
if(fp)
{
fseek(fp,0,SEEK_END);
if(ftell(fp) > m_maxfilesize)
{
fclose(fp);
continue;
}
fclose(fp);
}
break;
}
}

void inline CSimpleLog::Save()
{
//判断是否需要转存
if(m_output == 0)
{
return;
}

std::ofstream::pos_type pos = m_output->tellp();
if(pos > m_maxfilesize)
{
m_output->flush();
m_output->clear();
//basic_filebuf * p = m_output->rdbuf()->close();
m_output->close();
}
else
{
m_output->flush();
return;
}

char filename[255];
GetNewFileName(filename);
m_output->open(filename,ios::out|ios::ate|ios::app);
}

里面的 class MyOSMutex 定义和实现
class MyOSMutex
{
public:
MyOSMutex();
~MyOSMutex();

void Lock();
void Unlock();

bool TryLock();
private:

#ifdef WIN32
CRITICAL_SECTION fMutex;
#else
pthread_mutex_t fMutex;
#endif
};

MyOSMutex::MyOSMutex()
{
#ifdef WIN32
::InitializeCriticalSection(&fMutex);
#else
(void)pthread_mutex_init(&fMutex,0);
#endif
}

MyOSMutex::~MyOSMutex()
{
#ifdef WIN32
::DeleteCriticalSection(&fMutex);
#else
pthread_mutex_destroy(&fMutex);
#endif
}

void MyOSMutex::Lock()
{
#ifdef WIN32
::EnterCriticalSection(&fMutex);
#else
(void)pthread_mutex_lock(&fMutex);
#endif
}

void MyOSMutex::Unlock()
{
#ifdef WIN32
::LeaveCriticalSection(&fMutex);
#else
pthread_mutex_unlock(&fMutex);
#endif
}

bool MyOSMutex::TryLock()
{
#ifdef WIN32

// Return values of this function match our API
//#define _WIN32_WINNT 0x0500
/*
if(::TryEnterCriticalSection(&fMutex) == 0)
{
return false;
}
*/
#else
int theErr = pthread_mutex_trylock(&fMutex);
if(theErr != 0)
{
assert(theErr == EBUSY);
return false;
}
#endif
return true;
}





[解决办法]

在写log阿,刺激,多线程要格外小心啊,呵呵,观察中
[解决办法]
if(pos > m_maxfilesize)
{
m_output- >flush();
m_output- >clear();
//basic_filebuf * p = m_output- >rdbuf()- >close();
m_output- >close();
>>> m_output = NULL;
>>> other clean-up code
}
[解决办法]

2楼点出问题了,试着加把锁吧

读书人网 >C++

热点推荐