【问题标题】:Two separate tm structs mirroring each other两个独立的 tm 结构相互镜像
【发布时间】:2011-03-04 02:01:58
【问题描述】:

这是我目前的情况:

  • 我有两个 tm 结构,都设置为当前时间
  • 我在其中一个结构中更改了小时
  • 变化神奇地发生在另一个结构中......
  • 如何防止这种情况发生?我需要能够比较并知道两个不同时间之间的秒数——当前时间和未来时间。我一直在使用 difftime 和 mktime 来确定这一点。我认识到我在技术上不需要两个 tm 结构(另一个结构可能只是加载了原始时间的 time_t),但我仍然有兴趣了解为什么会发生这种情况。

void Tracker::monitor(char* buffer){

// time handling
time_t systemtime, scheduletime, currenttime;
struct tm * dispatchtime;
struct tm * uiuctime;
double remainingtime;


// let's get two structs operating with current time
dispatchtime = dispatchtime_tm();
uiuctime = uiuctime_tm();

// set the scheduled parameters
dispatchtime->tm_hour = 5;
dispatchtime->tm_min = 05;
dispatchtime->tm_sec = 14;

uiuctime->tm_hour = 0;

    // both of these will now print the same time! (0:05:14)
    // what's linking them??

// print the scheduled time
printf ("Current Time :  %2d:%02d:%02d\n", uiuctime->tm_hour, uiuctime->tm_min, uiuctime->tm_sec);
printf ("Scheduled Time :  %2d:%02d:%02d\n", dispatchtime->tm_hour, dispatchtime->tm_min, dispatchtime->tm_sec);

}

struct tm* Tracker::uiuctime_tm(){
    time_t uiucTime;
    struct tm *ts_uiuc;

    // give currentTime the current time
    time(&uiucTime);

    // change the time zone to UIUC
    putenv("TZ=CST6CDT");
    tzset();

    // get the localtime for the tz selected
    ts_uiuc = localtime(&uiucTime);

    // set back the current timezone
    unsetenv("TZ");
    tzset();

    // set back our results
    return ts_uiuc;
}

struct tm* Tracker::dispatchtime_tm(){
    time_t currentTime;
    struct tm *ts_dispatch;

    // give currentTime the current time
    time(&currentTime);

    // get the localtime for the tz selected
    ts_dispatch = localtime(&currentTime);

    // set back our results
    return ts_dispatch;
}

【问题讨论】:

    标签: c++ time linked-list time-t


    【解决方案1】:

    你必须这样做:

    struct tm* temp_tm;
    struct tm dispatchtime; // No longer a pointer
    struct tm uiuctime;     // No longer a pointer
    
    temp_tm = dispatchtime_tm();
    dispatchtime = *temp_tm; // Member to member copy
    
    temp_tm = uiuctime_tm();
    uiuctime = *temp_tm; // Member to member copy
    

    这样您将保留tm 结构的本地副本。这个结构是在标准库内部分配的,每次调用localtime都会指向同一个内存地址!

    【讨论】:

    • 您的解决方案本可以更简单。我不确定您为什么先分配给 temp_tm 然后分配给最终 tm,以下工作也有效: dispatchtime = *dispatchtime_tm(); uiuctime = *uiuctime_tm();
    • 你是对的。我的示例使用了一个中间步骤,只是为了尽可能易于理解和阅读。
    • 明白。我很欣赏这种清晰,在我看了你的解决方案后,我只是傻眼了片刻,为什么你包括了这一步。
    【解决方案2】:

    http://www.cplusplus.com/reference/clibrary/ctime/localtime/

    此结构由函数 gmtime 和 localtime 静态分配和共享。每次调用这些函数中的任何一个时,都会覆盖此结构的内容。

    您需要将值从结构中复制出来。您的函数可以按值返回 tm 结构,您可以取消引用主程序中的函数等。

    【讨论】:

    • 但是先调用localtime,然后修改struct。我看不出你引用的内容的相关性。
    • @BSchlinker struct是通过指针返回并存储的,但是两个不同的指针都指向同一个静态内存。
    • uiuctime_tmdispatchtime_tm 中,您只需返回通过调用localtime 给出的指针。在您的主程序中,您存储的是相同的指针。该指针将始终指向同一个结构。通过在dispatchtime_tm 之后调用uiuctime_tm,您将覆盖结构。您需要从结构中复制数据,因为所有指针始终指向相同的数据。
    【解决方案3】:

    实际上你根本没有两个不同的 tm 结构。你所拥有的是两个 tm 结构指针,它们都指向本地时间返回的同一个静态结构。因此,看起来对一个结构的更改会影响另一个,但实际上它只是一个结构有两个不同的指针。

    解决这个问题最安全的方法是不要依赖localtime的静态结构,而是使用localtime_r,这需要你传入你自己的tm结构指针,然后将其填写。例如:

    void Tracker::uiuctime_tm(struct tm* out){
        time_t uiucTime;
    
        // give currentTime the current time
        time(&uiucTime);
    
        // change the time zone to UIUC
        putenv("TZ=CST6CDT");
        tzset();
    
        // get the localtime for the tz selected, and set back the result into the output parameter.
        localtime_r(&uiucTime, out);
    
        // set back the current timezone
        unsetenv("TZ");
        tzset();
    }
    
    struct tm uiuctime;
    uiuctime_tm(&uiuctime);
    

    【讨论】:

    • 感谢您对 localtime_r 的解释。它没有在 cplusplus.com 上列出,所以我不知道。
    猜你喜欢
    • 2023-03-18
    • 2019-05-14
    • 2022-07-11
    • 1970-01-01
    • 2022-06-29
    • 1970-01-01
    • 1970-01-01
    • 2017-03-11
    • 2023-01-13
    相关资源
    最近更新 更多