c++ FILE* 在放入map中之后,指向了错误的句柄,导致fprintf出错

img


程序出错
代码如下



#include <string>
#include <sstream>
#include <fstream>
#include <iostream>
#include <iomanip>
#include <time.h>
#include <map>
#include <windows.h>
#include <thread>


using namespace std;

//日志级别的提示信息
static const char * KEYINFOPREFIX = " Key: \n";
static const char * ERRORPREFIX = " Error: \n";
static const char * WARNINGPREFIX = " Warning: \n";
static const char * INFOPREFIX = " Info: \n";

static const int MAX_STR_LEN = 1024;
//日志级别枚举
typedef enum EnumLogLevel
{
    LogLevelAll = 0, //所有信息都写日志
    LogLevelMid, //写错误、警告信息
    LogLevelNormal, //只写错误信息
    LogLevelStop //不写日志
};

#include <Windows.h>

#include <stdio.h>

using namespace std;
/*
* 类名:Logger
* 作用:提供写日志功能,支持多线程,支持可变形参数操作,支持写日志级别的设置
* 接口:SetLogLevel:设置写日志级别
TraceKeyInfo:忽略日志级别,写关键信息
TraceError:写错误信息
TraceWarning:写警告信息
TraceInfo:写一般信息
*/
class Logger
{
public:
    //默认构造函数
    Logger();
    //构造函数
    Logger(const char * strLogPath, EnumLogLevel nLogLevel = EnumLogLevel::LogLevelNormal);
    //析构函数
    virtual ~Logger();
public:
    friend class Data_list;
    friend class My_MdSpi;
    friend class CTraderSpi;


    //写关键信息
    void TraceKeyInfo(const char * strInfo, ...);
    //写错误信息
    void TraceError(const char* strInfo, ...);
    //写警告信息
    void TraceWarning(const char * strInfo, ...);
    //写一般信息
    //void TraceInfo(const char * strInfo, ...);
    void TraceInfo(const string strInfo, ...);
    //设置写日志级别
    void SetLogLevel(EnumLogLevel nLevel);
private:
    //写文件操作
    void Trace(const char * strInfo);
    //void TraceInfo(const string & strInfo, ...);


    //获取当前系统时间
    char * GetCurrentTime();
    //创建日志文件名称
    void GenerateLogName();
    //创建日志路径
    void CreateLogPath();
    string  GetCurrentTimeStamp(int time_stamp_type);
private:
    //写日志文件流
    FILE * m_pFileStream;
    //写日志级别
    EnumLogLevel m_nLogLevel;
    //日志的路径
    char m_strLogPath[MAX_STR_LEN];
    //日志的名称
    char m_strCurLogName[MAX_STR_LEN];
    //线程同步的临界区变量
    CRITICAL_SECTION m_cs1;
    //时间戳类型
    int time_stamp_type;
};

class Data_list :private Logger {
private:



public:
    Data_list();

    Data_list(const char * loggerpath_chrone);

    ~Data_list();

    void InitMyMarketData();




};

Data_list::Data_list()
{
    cout << "Data_list   默认构造函数" << endl;
}

Data_list::Data_list(const char*loggerpath_chrone) : Logger(loggerpath_chrone) {

    cout << "Data_list   构造函数" << endl;
}
Data_list::~Data_list()
{
}

void Data_list::InitMyMarketData()
{
    ostringstream s_s;
    s_s.fill('0');

    s_s << "开始下单  s_insert:";
    Logger::TraceInfo(s_s.str());
}
#include <imagehlp.h>
#include <time.h>
#include <string.h>
#include <stdarg.h>


#include <ctime>
#include <string>
#include <chrono>
#include <sstream>
#include <iostream>
#pragma warning(disable : 4996)
#pragma comment(lib, "DbgHelp.lib")

//默认构造函数
Logger::Logger()
{
    ////初始化
    cout << "Logger        默认构造函数" << endl;
    //memset(m_strLogPath, 0, MAX_STR_LEN);
    //memset(m_strCurLogName, 0, MAX_STR_LEN);
    //m_pFileStream = NULL;
    ////设置默认的写日志级别
    ////m_nLogLevel = EnumLogLevel::LogLevelNormal;
    //m_nLogLevel = EnumLogLevel::LogLevelAll;
    //time_stamp_type = 3;
    ////初始化临界区变量
    //InitializeCriticalSection(&m_cs1);
    ////创建日志文件名
    //GenerateLogName();
}

//构造函数
Logger::Logger(const char * strLogPath, EnumLogLevel nLogLevel) :m_nLogLevel(nLogLevel)
{
    //初始化
    cout << "Logger      构造函数" << endl;
    m_pFileStream = NULL;
    m_nLogLevel = EnumLogLevel::LogLevelAll;
    time_stamp_type = 3;
    strcpy(m_strLogPath, strLogPath);
    InitializeCriticalSection(&m_cs1);
    CreateLogPath();
    GenerateLogName();
}

//析构函数
Logger::~Logger()
{
    //释放临界区
    DeleteCriticalSection(&m_cs1);
    //关闭文件流
    if (m_pFileStream)
        fclose(m_pFileStream);
}

//写关键信息接口
void Logger::TraceKeyInfo(const char * strInfo, ...)
{
    if (!strInfo)
        return;
    char pTemp[MAX_STR_LEN] = { 0 };
    strcpy(pTemp, GetCurrentTime());
    strcpy(pTemp, GetCurrentTimeStamp(time_stamp_type).c_str());
    strcat(pTemp, KEYINFOPREFIX);
    //获取可变形参
    va_list arg_ptr = NULL;
    va_start(arg_ptr, strInfo);
    vsprintf(pTemp + strlen(pTemp), strInfo, arg_ptr);
    va_end(arg_ptr);
    //写日志文件
    Trace(pTemp);
    arg_ptr = NULL;

}

//写错误信息
void Logger::TraceError(const char* strInfo, ...)
{
    //判断当前的写日志级别,若设置为不写日志则函数返回
    if (m_nLogLevel >= EnumLogLevel::LogLevelStop)
        return;
    if (!strInfo)
        return;
    char pTemp[MAX_STR_LEN] = { 0 };
    strcpy(pTemp, GetCurrentTime());
    strcat(pTemp, ERRORPREFIX);
    va_list arg_ptr = NULL;
    va_start(arg_ptr, strInfo);
    vsprintf(pTemp + strlen(pTemp), strInfo, arg_ptr);
    va_end(arg_ptr);
    Trace(pTemp);
    arg_ptr = NULL;
}

//写警告信息
void Logger::TraceWarning(const char * strInfo, ...)
{
    //判断当前的写日志级别,若设置为只写错误信息则函数返回
    if (m_nLogLevel >= EnumLogLevel::LogLevelNormal)
        return;
    if (!strInfo)
        return;
    char pTemp[MAX_STR_LEN] = { 0 };
    strcpy(pTemp, GetCurrentTime());
    strcat(pTemp, WARNINGPREFIX);
    va_list arg_ptr = NULL;
    va_start(arg_ptr, strInfo);
    vsprintf(pTemp + strlen(pTemp), strInfo, arg_ptr);
    va_end(arg_ptr);
    Trace(pTemp);
    arg_ptr = NULL;
}

//写一般信息
void Logger::TraceInfo(const string strInfo, ...)
{
    //判断当前的写日志级别,若设置只写错误和警告信息则函数返回
    if (m_nLogLevel >= EnumLogLevel::LogLevelMid)
        return;
    if (!strInfo.c_str())
        return;
    char pTemp[MAX_STR_LEN] = { 0 };
    //strcpy(pTemp, GetCurrentTime());
    strcpy(pTemp, GetCurrentTimeStamp(time_stamp_type).c_str());
    strcat(pTemp, INFOPREFIX);
    va_list arg_ptr = NULL;
    va_start(arg_ptr, strInfo);
    vsprintf(pTemp + strlen(pTemp), strInfo.c_str(), arg_ptr);
    va_end(arg_ptr);
    Trace(pTemp);
    arg_ptr = NULL;
}

//获取系统当前时间
char * Logger::GetCurrentTime()
{
    time_t curTime;
    struct tm * pTimeInfo = NULL;
    time(&curTime);
    pTimeInfo = localtime(&curTime);
    char temp[MAX_STR_LEN] = { 0 };
    sprintf(temp, "%02d:%02d:%02d", pTimeInfo->tm_hour, pTimeInfo->tm_min, pTimeInfo->tm_sec);
    char * pTemp = temp;
    return pTemp;
}

//设置写日志级别
void Logger::SetLogLevel(EnumLogLevel nLevel)
{
    m_nLogLevel = nLevel;
}

//写文件操作
void Logger::Trace(const char * strInfo)
{
    if (!strInfo)
        return;
    try
    {
        //进入临界区
        EnterCriticalSection(&m_cs1);
        //若文件流没有打开,则重新打开
        if (!m_pFileStream)
        {
            char temp[1024] = { 0 };
            strcat(temp, m_strLogPath);
            strcat(temp, m_strCurLogName);
            m_pFileStream = fopen(temp, "a+");
            if (!m_pFileStream)
            {
                return;
            }
        }
        //写日志信息到文件流
        fprintf(m_pFileStream, "%s\n", strInfo);
        fflush(m_pFileStream);
        //离开临界区
        LeaveCriticalSection(&m_cs1);
    }
    //若发生异常,则先离开临界区,防止死锁
    catch (...)
    {
        LeaveCriticalSection(&m_cs1);
    }
}

//创建日志文件的名称
void Logger::GenerateLogName()
{
    time_t curTime;
    struct tm * pTimeInfo = NULL;
    time(&curTime);
    pTimeInfo = localtime(&curTime);
    char temp[1024] = { 0 };
    //日志的名称如:2013-01-01.log
    sprintf(temp, "%04d-%02d-%02d.log", pTimeInfo->tm_year + 1900, pTimeInfo->tm_mon + 1, pTimeInfo->tm_mday);
    if (0 != strcmp(m_strCurLogName, temp))
    {
        strcpy(m_strCurLogName, temp);
        if (m_pFileStream)
            fclose(m_pFileStream);
        char temp[1024] = { 0 };
        strcat(temp, m_strLogPath);
        strcat(temp, m_strCurLogName);
        //以追加的方式打开文件流
        m_pFileStream = fopen(temp, "a+");
        fprintf(m_pFileStream, "%s\n", "aassdd");
        fflush(m_pFileStream);
    }

}



//创建日志文件的路径
void Logger::CreateLogPath()
{
    if (0 != strlen(m_strLogPath))
    {
        strcat(m_strLogPath, "\\");
    }
    MakeSureDirectoryPathExists(m_strLogPath);
}


string  Logger::GetCurrentTimeStamp(int time_stamp_type = 2)
{
    chrono::system_clock::time_point now = std::chrono::system_clock::now();

    time_t now_time_t = std::chrono::system_clock::to_time_t(now);
    tm* now_tm = std::localtime(&now_time_t);

    char buffer[128];
    strftime(buffer, sizeof(buffer), "%F %T", now_tm);

    std::ostringstream ss;
    ss.fill('0');

    std::chrono::milliseconds ms;
    std::chrono::microseconds cs;
    std::chrono::nanoseconds ns;

    switch (time_stamp_type)
    {
    case 0:
        ss << buffer;
        break;
    case 1:
        ms = std::chrono::duration_cast<std::chrono::milliseconds>(now.time_since_epoch()) % 1000;
        ss << buffer << ":" << ms.count();
        break;
    case 2:
        ms = std::chrono::duration_cast<std::chrono::milliseconds>(now.time_since_epoch()) % 1000;
        cs = std::chrono::duration_cast<std::chrono::microseconds>(now.time_since_epoch()) % 1000;
        ss << buffer << ":" << ms.count() << ":" << cs.count() % 1000;
        break;
    case 3:
        ms = std::chrono::duration_cast<std::chrono::milliseconds>(now.time_since_epoch()) % 1000;
        cs = std::chrono::duration_cast<std::chrono::microseconds>(now.time_since_epoch()) % 1000;
        ns = std::chrono::duration_cast<std::chrono::nanoseconds>(now.time_since_epoch()) % 1000;
        ss << buffer << ":" << ms.count() << ":" << cs.count() << ":" << ns.count();
        break;
    default:
        ss << buffer;
        break;
    }
    string pTemp;
    pTemp.assign(ss.str());
    //strcpy(pTemp.c_str(), ss.str().c_str());
    return pTemp;
}
map<string, class Data_list> multi_ins_map;

int main(int argc, char *argv[])
{


    char oggerpath_chrone[] = ".\\Logger_chrone\\";


    class Data_list data_list(oggerpath_chrone);

    string asd = "asd";
        multi_ins_map.insert(pair<string, class Data_list>(asd, data_list));
    //class Data_list data_list();
        //multi_ins_map[asd] = data_list;
        multi_ins_map[asd].InitMyMarketData();
    //data_list.InitMyMarketData();
    getchar();
}

fprintf(m_pFileStream, "%s\n", strInfo);这一行出错了,不知道是什么原因。
但如果主程序里把

        multi_ins_map.insert(pair<string, class Data_list>(asd, data_list));


替换成


        multi_ins_map[asd] = data_list;

就好了。
这个程序是我从项目当中抽出来的。在我的项目当中哪样的map貌似都不行。

主要我写log是一个类,然后我的项目是通过继承log这个类。但我的项目需要实例化很多类,所以要把实例化的类整合到一个容器当中。整合的时候我用的是map,在map中就出错了

这是个 map 使用的问题
map.insert 如果键已经存在,则不会添加
map[key] = value 则会覆盖掉原来的键值对

要么查找 key ,存在则 erase 掉 再 insert
要么 就用 []