代码之家  ›  专栏  ›  技术社区  ›  Alex Lee

为什么在使用mktime处理指针和非指针时difftime()会导致不同的结果?

  •  -1
  • Alex Lee  · 技术社区  · 10 年前

    我尝试使用

        difftime(time_t end, time_t mktime(start) ) 
    

    以两种不同的方式计算两个不同时间之间的差异。只是为了好奇,我发现它会导致不同的结果,失败和成功。我不知道为什么会这样?

    为什么在以下两种情况下会产生不同的结果?

        // Failure Case 1     when execution, segmentation fault
        time_t end;
        time(&end);
    
        struct tm * start;   // defining a pointer
    
        start->tm_hour = 0;
        start->tm_min  = 0;
        start->tm_sec  = 0;
        start->tm_year = 114;
        start->tm_mon  = 6;
        start->tm_mday = 29;
    
        double second = difftime(end, mktime(start) ); // where problem come from!
    
        // Success Case 2, with expected result
        time_t end;
        time(&end);       
    
        struct tm start;   // defining a non-pointer
    
        start.tm_hour = 0;
        start.tm_min  = 0;
        start.tm_sec  = 0;
        start.tm_year = 114;
        start.tm_mon  = 6;
        start.tm_mday = 29;
    
        double second = difftime(end, mktime( &start) );
    
    1 回复  |  直到 10 年前
        1
  •  3
  •   Mats Petersson    10 年前

    原始情况1不分配内存,两种情况都不清除 tm 结构,这可能是获得正确结果所必需的(当然也是一种“好的做法”)。

    要解决C中的情况1,最好的解决方案是使用 calloc :

    struct tm *start = calloc(1, sizeof(struct tm)); 
    
    start->tm_year = 114;
    start->tm_mon  = 6;
    start->tm_mday = 29;
    

    然后当你不再需要 start 价值,使用

    free(start);
    

    (请注意,由于结构中填充了零,因此不再需要手动设置小时、分钟、秒)

    在C++中,您可以使用 new 而是:

    tm *start = new tm(); 
    ...
    // After it is finished. 
    delete start
    

    中的空括号 tm() 使其在分配实际内存后“填充零值”。

    首选“案例2”变体,因为它分配了 开始 堆栈上的变量。

    情况1有些糟糕,因为为小数据结构分配内存(小通常意味着小于1KB左右,但这取决于实际运行环境,64KB RAM的手表可能比16GB RAM的台式机有更严格的要求,而手机可能介于两者之间,这在一定程度上取决于它是什么类型的手机)。避免“小”内存分配至少有两个原因:

    1. 它需要更多的内存,因为所有已知的分配器都使用一些额外的内存来跟踪实际分配的内存块。
    2. 这需要额外的时间,因为 分配 比堆栈上的分配复杂得多 {c,m}alloc 打电话就可以半打,同样的 delete free ,以及这些库函数中的几十到几千条指令(代码的长度在很大程度上取决于它的实现方式,以及运行时是否有一些“可用内存”,或者是否需要调用操作系统来“获得更多内存”)。当然,你需要跟踪分配情况,而不是“泄露”分配情况

    对于情况2,您可以使用:

    struct tm start = {}; 
    

    (同样,您不需要为小时、分钟和秒设置零值)

    在C++中,省略是正确的 struct 自从 struct tm { ... }; 相关头文件中的声明使名称 tm公司 无论如何表示结构-这适用于所有 结构 class 名称-唯一的例外是相同的名称以不同的方式使用,例如,有一个函数或变量 tm公司 在相同的上下文中-在这种情况下,编译器会给出一些错误,表示“不理解你的意思” tm公司 这里“[确切的措辞因使用的编译器而异]。

    由于最初的问题同时指定了C和C++,我试图解释