变长参数列表的转义字符处理

文章描述了在C语言中使用stdarg.h处理变长参数时遇到的问题,特别是涉及到含有%转义字符的日志记录。当尝试将包含多字节字符(如中文汉字)的URL写入日志时,程序出现异常,而使用printf函数则没有问题。问题出现在自定义的日志函数中,可能由于参数长度计算不准确导致。测试案例展示了问题的具体表现,日志文件未能正确输出含有转义字符的内容。
摘要由CSDN通过智能技术生成

C语言使用stdarg.h中有一些处理变长参数的宏,va_start、va_list、va_end...在进行日志处理时,这个变长参数列表很好用,类似printf的函数原型。
以前一直使用得很好的,最近在记录url的时候出现了问题,url中会有一些使用%转义多字节字符(中文汉字等)的情况,将这些参数送进去程序会出现异常。 但是使用printf是没有问题的。

以下是我的问题代码及相关输出结果

#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <time.h>
#include <string.h>

#ifdef LOGDEBUG
#define LOGFILE_NAME "logtest.log"
FILE* LOGFILE;
void LOGON() {
    LOGFILE=fopen(LOGFILE_NAME,"a+");
}
void LOG(const char* format,...) {
    va_list list;
    time_t t=time(NULL);
    tm* tp=localtime(&t);
    char log_spin[256]="";
    char log_buffer[1024*4]="";
    
    if(format==NULL||!LOGFILE) return;
    
    sprintf(log_spin,"[%04d-%02d-%02d %02d:%02d:%02d]",
            tp->tm_year+1900,tp->tm_mon+1,tp->tm_mday,
            tp->tm_hour,tp->tm_min,tp->tm_sec);
    strcpy(log_buffer,log_spin);
    size_t occuppied=strlen(log_buffer);
    size_t remain=sizeof(log_buffer)-occuppied;
    int count=0;
    
    va_start(list,format);
    count=vsnprintf(&log_buffer[strlen(log_buffer)],remain,format,list);
    va_end(list);
    
    //隐患,如果参数长度超长,函数会bug.
    if(count>=remain) sprintf(&log_buffer[sizeof(log_buffer)-5],"...\n\0");
    else log_buffer[strlen(log_buffer)]='\n';
    
    fprintf(LOGFILE,log_buffer);
    fflush(LOGFILE);
}
void LOGOFF() {
    LOG("Exit!\n\n\n");
    if(LOGFILE) fclose(LOGFILE);
}

void test() {
    FILE* file=NULL;
    int length=0;
    char* mem=NULL;

#define TEST_FILENAME "转义文件"    
    file=fopen(TEST_FILENAME,"rb");
    if(!file) return;
    
    fseek(file,0,SEEK_END);
    length=ftell(file);
    
    mem=(char*)calloc(sizeof(char)*(length+1),1);
    if(!mem) {
        fclose(file);
        return;
    }
    
    fseek(file,0,SEEK_SET);
    fread(mem,length,1,file);
    
    fclose(file);
    
    printf("%s\n",mem);
    LOG("%s:%s",__FUNCTION__,mem);
    
    if(mem) free(mem);
    
    return;
}

void main() {
    char msg[256]="%7B";//"";
    LOGON();
    LOG("%s:%s",__FUNCTION__,msg);   
    test();
    LOGOFF();
    printf("Exit.\n");
}
#endif

测试文件内容如下:

输出结果如下:

日志文件如下:

可以看到,日志文件并没有正常输出转义文件的内容。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 11
    评论
评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值