linux下写了一个log文件的功能,利用消息队列实现log信息的传输,有多个进程写入log消息,一个线程来读取log信息并写入log文件,然后当log文件大于5MB时,新建一个新的log文件并继续记录log信息。目前正常启动记录都没问题,问题出在新建log文件的时候,旧的log文件顺利关闭,新log文件已经建立,但是马上就出现了segmentation fault!  查了好久,也没找到原因,请教诸位高手帮忙分析下,谢谢!代码如下:uint32_t get_file_size(const char *path)
{
    uint32_t file_size;
    fseek(My_sys_log.fd, 0L, SEEK_END );
    file_size=ftell(My_sys_log.fd);
    return file_size;
}int  create_ipc_qid()
{
      int  msgqid;      msgqid = msgget(MSGKEY, IPC_CREAT|0666);    /*检查消息队列是否存在*/
      if(msgqid < 0)
      {
        msgqid = msgget(MSGKEY,IPC_CREAT|0666);/*创建消息队列*/
        if(msgqid <0)
        {
            printf("failed to create msq | errno=%d [%s]\n",errno,strerror(errno));
            exit(-1);
        }
      }
      return msgqid;
}void send_message(int qid, char *text)
{
    ipc_msg MSG;
    memset(&MSG, 0, sizeof(MSG));
MSG.msg_type = Msg_type;
strcpy(MSG.mtext, text);
   //把一条消息添加到消息队列,IPC_NOWAIT表示队列满不等待,返回EAGAIN错误
if((msgsnd(qid, &MSG, sizeof(MSG)-sizeof(long), IPC_NOWAIT)) ==-1)
//if((msgsnd(qid, &MSG, sizeof(MSG)-sizeof(long), 0)) ==-1)
{
   perror("msgsnd");
       exit(1);
    }
}ipc_msg read_message(int qid)
{
    ipc_msg MSG;
    int ret;
    memset(&MSG, 0, sizeof(MSG));
    //IPC_NOWAIT: 调用进程会立即返回。若没有收到消息则立即返回 -1。
    ret=msgrcv(qid, &MSG, sizeof(MSG)-sizeof(long), (long)Msg_type,0);
    if(ret==-1)
    {
        printf("recv message err\n");
        perror("msgrcv");
        exit(1);
        //return -1;
    }
    return MSG;
}void remove_queue(int qid)
{
    msgctl(qid, IPC_RMID, 0);
}uint8_t syslog_init()
{
    DIR *dirptr = NULL;
    char *log_init="Create new syslog file sucessful!\n";
    memset(My_sys_log.file_path,'\0',40);
    time_z now;
    Time_get(&now);
    printf("get time now\n");
    printf("file flag is %d\n",file_flag);
    if(dirptr = opendir("/media/My_SDcard/Debug") == NULL)
    {
        printf("not have /media/My_SDcard/Debug folder\n");
        system("mkdir  /media/My_SDcard/Debug ");
    }
    else
    {
        printf("open dir sucessful\n");
        closedir(dirptr);
    }
   // sprintf(s_log_info.file_path,"/media/mmcblk0p1/Debug/S1_Debug_%d_%d_%d_%d_%d_%d.txt",now.year+2000,now.mon,now.day,now.hour,now.min,now.sec);
    //sprintf(s_log_info.file_path,"/media/My_SDcard/Debug/S1_Debug_%d_%02d_%02d_%02d_%02d_%02d.txt",now.year,now.mon,now.day,now.hour,now.min,now.sec);
    if(file_flag==0)
        sprintf(My_sys_log.file_path,"/media/My_SDcard/Debug/S1_Debug_2017_12_25_19_17_31.txt");
    else
    //sprintf(My_sys_log.file_path,"/media/My_SDcard/Debug/S1_Debug_%d_%02d_%02d_%02d_%02d_%02d.txt",now.year,now.mon,now.day,now.hour,now.min,now.sec);
        sprintf(My_sys_log.file_path,"/media/My_SDcard/Debug/S1_Debug_2017_12_25_19_18_31.txt");    printf("file path is %s\n",My_sys_log.file_path);    My_sys_log.fd = fopen(My_sys_log.file_path,"a+");
    printf("open the log file init ucessful\n");
    //printf("s_log_info.fd=%x\n",My_sys_log.fd);
    if(My_sys_log.fd == NULL)
    {
        perror("fail to fopen syslog file");
        return -1;
    }
    else
    {
        fwrite(log_init,strlen(log_init),1,My_sys_log.fd);
        fflush(My_sys_log.fd);
        printf("write the initial log,new file fd is %d\n",My_sys_log.fd);
    }
     return true;
}void *Evl_Engine_Thread_entry(void *argv)
{
    uint32_t file_size;
    //int len=0;
    //PNode Msg_Node;
    //Frame  Msg_Frame_W;
    int fpclose;
    ipc_msg Log_Msg;
    char *buf;
    int temp1=0;
    //time_z now;
    //char *log_init="Create new syslog file sucessful!\n";    while(1)
    {
        file_size = get_file_size(My_sys_log.file_path);             //得到已经打开文件的大小
        //len = GetSize(Msg_Queue);
        printf("my file size is %d\n",file_size);
        if(file_size > FILE_SIZE_MAX)                                     //文件大于5M重新打开新的文件
        //if(1)
        {            printf("file size is largger than 5MB\n");
            fpclose = fclose(My_sys_log.fd);
            printf("close the file %d,fpclose is %d\n",My_sys_log.fd,fpclose);
            file_flag = 1;
            syslog_init();
        }
        else
        {            Log_Msg = read_message(MSG_QID);
            printf("write date\n");
            buf = Log_Msg.mtext;
            printf("log msg is %s\n",buf);
            fwrite(buf,strlen(buf),1,My_sys_log.fd);
            //printf("write msg sucessful\n");
            fflush(My_sys_log.fd);
        }    }
}

解决方案 »

  1.   

    file_path 的定义是40大小?你数数你保存的文件名字是多少字节?
      

  2.   

    file_path的长度改为100个,还是同样的问题。
    其实新的log文件已经建立了,而且也成功写入了第一句Create new syslog file sucessful!,测试结果是到消息队列读取的时候就出现了segmentation fault。但是这个消息队列读取在log文件不到5M的时候一直正常的,只是在新建log文件后读取消息产生了异常,感觉前后两种情况下消息队列没有什么变化啊,怎么会出现了段错误了
    下面是出现错误时候的提示信息:my file size is 5242884
    file size is largger than 5MB
    close the file 294992,fpclose is 0
    get time now
    file flag is 1
    open dir sucessful
    file path is /media/My_SDcard/Debug/S1_Debug_2017_12_25_19_18_31.txt
    open the log file init ucessful
    write the initial log,new file fd is 294992
    my file size is 34
    Segmentation fault
      

  3.   

    两个办法排查:
    1. 用gdb打开core文件
    2. 用valgrind执行下程序,会检查出内存越界的地方。