Valgrind 条件跳转或移动取决于未初始化的值 mktime() 或浅拷贝问题

Valgrind Conditional jump or move depends on uninitialised value(s) mktime() or shallow copy issue

浏览了各种资源以寻求解决方案,但找不到问题所在。我试图在 validate_date(char * date, time_t datefrom, time_t dateto); 中将字符串(格式化为 time_t 转换)转换为 time_t。

错误表明我正在访问一个未初始化的变量,参数 char * date 是可访问的(通过打印)并且是 malloced,time_t datefrom、dateto 都包含 0。

代码:

void test_print(CalComp * comp_cpy){
    printf("Test print of copy...\n");

    for(int i = 0; i < comp_cpy->ncomps; i++){
        printf("Object: (%s)\n", comp_cpy->comp[i]->name);
    }
}

/*make a shallow copy of CalComp*/
CalComp * event_copy(CalComp * comp){
    CalComp * cpy = malloc(sizeof(CalComp) + comp->ncomps * sizeof(CalComp*));
    *cpy = *comp;
    memcpy(cpy->comp, comp->comp, comp->ncomps * sizeof(CalComp*));
    return cpy;
}


/*check if date is between datefrom and dateto*/
bool validate_date(char * date, time_t datefrom, time_t dateto){
    struct tm tm;

    char temp[1000], *token;

    strcpy(temp,date);
    token = strtok(temp, "Z");

    if(strptime(token, "%Y%m%dT%H%M%S", &tm)==NULL){ //check if conversion to struct tm is successful
            perror("validate_date converting date error");
            exit(-1);

    }

    time_t tm_date;

    if((tm_date = mktime(&tm)) == -1){   //LINE 494 ERROR 
        perror("validate_date mktime error");
        exit(-1);
    }

    if(datefrom == 0 && dateto == 0) return true; 

    double difference_from, difference_to, difference;

    if(datefrom > 0 && dateto > 0){

        difference_from = difftime(tm_date, datefrom);
        difference_to = difftime(dateto, tm_date);
        if(difference_from>0 && difference_to>0) return true; 
    }

    else if(datefrom > 0 && dateto == 0){
        if((difference = difftime(tm_date, datefrom))>0) return true;
    }

    else if(datefrom == 0 && dateto > 0)
        if((difference = difftime(dateto, tm_date))>0) return true;

    return false;

}

Valgrind 错误:

    CalFilter...
temp->value: (20160218T175508Z)
==25873== Conditional jump or move depends on uninitialised value(s)
==25873==    at 0x1002036D6: _st_time1 (in /usr/lib/system/libsystem_c.dylib)
==25873==    by 0x1002039A7: mktime (in /usr/lib/system/libsystem_c.dylib)
==25873==    by 0x100002856: validate_date (main.c:494)
==25873==    by 0x100002B7D: event_date_range (main.c:532)
==25873==    by 0x100002CB7: comp_copy (main.c:559)
==25873==    by 0x100002E15: calFilter (main.c:589)
==25873==    by 0x100003156: main (main.c:647)
==25873== 
temp->value: (20160218T175723Z)
temp->value: (20160218T175816Z)
==25873== Conditional jump or move depends on uninitialised value(s)
==25873==    at 0x100204590: time2sub (in /usr/lib/system/libsystem_c.dylib)
==25873==    by 0x100203927: time2 (in /usr/lib/system/libsystem_c.dylib)
==25873==    by 0x1002036F6: _st_time1 (in /usr/lib/system/libsystem_c.dylib)
==25873==    by 0x1002039A7: mktime (in /usr/lib/system/libsystem_c.dylib)
==25873==    by 0x100002856: validate_date (main.c:494)
==25873==    by 0x100002B7D: event_date_range (main.c:532)
==25873==    by 0x100002CB7: comp_copy (main.c:559)
==25873==    by 0x100002E15: calFilter (main.c:589)
==25873==    by 0x100003156: main (main.c:647)
==25873== 
==25873== Conditional jump or move depends on uninitialised value(s)
==25873==    at 0x10020459C: time2sub (in /usr/lib/system/libsystem_c.dylib)
==25873==    by 0x100203927: time2 (in /usr/lib/system/libsystem_c.dylib)
==25873==    by 0x1002036F6: _st_time1 (in /usr/lib/system/libsystem_c.dylib)
==25873==    by 0x1002039A7: mktime (in /usr/lib/system/libsystem_c.dylib)
==25873==    by 0x100002856: validate_date (main.c:494)
==25873==    by 0x100002B7D: event_date_range (main.c:532)
==25873==    by 0x100002CB7: comp_copy (main.c:559)
==25873==    by 0x100002E15: calFilter (main.c:589)
==25873==    by 0x100003156: main (main.c:647)
==25873== 
temp->value: (20160218T180006Z)
temp->value: (20160218T180026Z)
temp->value: (20160218T180103Z)
temp->value: (20160218T180223Z)
temp->value: (20160218T175604Z)
Test print of copy...
Object: (VEVENT)
Object: (VEVENT)
Object: (VEVENT)
Object: (VEVENT)
Object: (VEVENT)
Object: (VEVENT)
Object: (VEVENT)
Object: (VEVENT)
(DTSTART)
(DTSTART)
(DTSTART)
(DTSTART)
==25873== Invalid read of size 1
==25873==    at 0x100012874: _platform_strcmp (in /usr/local/lib/valgrind/vgpreload_memcheck-amd64-darwin.so)
==25873==    by 0x100002E66: calFilter (main.c:595)
==25873==    by 0x100003156: main (main.c:647)
==25873==  Address 0x100a8b6f0 is 0 bytes inside a block of size 12 free'd
==25873==    at 0x10001044D: free (vg_replace_malloc.c:534)
==25873==    by 0x1000025AD: calExtract (main.c:429)
==25873==    by 0x100003106: main (main.c:645)
==25873==  Block was alloc'd at
==25873==    at 0x10000FEA1: malloc (vg_replace_malloc.c:303)
==25873==    by 0x100005265: parseCalProp (calutil.c:588)
==25873==    by 0x1000046E2: readCalComp (calutil.c:351)
==25873==    by 0x10000494B: readCalComp (calutil.c:402)
==25873==    by 0x1000049EA: readCalComp (calutil.c:410)
==25873==    by 0x1000049EA: readCalComp (calutil.c:410)
==25873==    by 0x1000049EA: readCalComp (calutil.c:410)
==25873==    by 0x1000049EA: readCalComp (calutil.c:410)
==25873==    by 0x100003AC6: readCalFile (calutil.c:222)
==25873==    by 0x10000300C: main (main.c:634)
==25873== 
(DTSTART)
(DTSTART)
(DTSTART)
(DTSTART)
==25873== Conditional jump or move depends on uninitialised value(s)
==25873==    at 0x100002EF3: calFilter (main.c:606)
==25873==    by 0x100003156: main (main.c:647)
==25873== 
==25873== 



enter code here

来自strptime man page:

In principle, this function does not initialize tm but only stores the values specified. This means that tm should be initialized before the call.

您已调用 strptime 来填写 tm 变量。但是,如上面的手册页摘录所述,strptime 可能不会设置 tm 变量中的所有字段。所以 valgrind 抱怨 tm 中的某些字段可能在未初始化的情况下使用。

因此您的代码需要在调用 strptime 之前显式初始化它。例如,使用初始化程序或使用 memset.

struct tm tm = { 0 };

memset(&tm, 0, sizeof(tm));