【问题标题】:Error in one tm-structure corrupting other tm-structures一个 tm 结构中的错误会破坏其他 tm 结构
【发布时间】:2017-03-11 17:02:48
【问题描述】:

我偶然发现了这种行为,想知道这是否是预期的(我觉得不合适)。

我在一个特定的 tm 结构中强制出错,而所有其他的都损坏了。

这是代码(精简到重现问题的最低限度)

int main()
{
    cout << "-----   Bug test - tm struc   -----" << endl;
    //--------------------------------------------

    //--- Setup struct tm ---
    time_t timet_Now = time(NULL);
    struct tm* tm1 = localtime(&timet_Now);
    struct tm* tm2 = localtime(&timet_Now);

    //--- Verify OK  -  cout shows "28/10/2016"---
    cout << tm1->tm_mday << " " << tm1->tm_mon << " " << tm1->tm_year << endl;
    cout << tm2->tm_mday << " " << tm2->tm_mon << " " << tm2->tm_year << endl;

    // ... so far, so good 

    // --- Force an error in a different tm struct (xxtm)
    time_t xtimet = 1464778020000;
    struct tm* xxtm = localtime(&xtimet);  //<<< xxtm = null - no runtime error

    //--- tm1 and tm2 are now corrupted - cout shows "-1/-1/-1"
    cout << tm1->tm_mday << " " << tm1->tm_mon << " " << tm1->tm_year << endl;
    cout << tm2->tm_mday << " " << tm2->tm_mon << " " << tm2->tm_year << endl;

    //--- This next line crashes the application, as tm1 is corrupted
    char* c = asctime(tm1);

    return 0;
}

崩溃错误是:MyTest.exe 中 0x0FA520B5 (ucrtbased.dll) 处出现未处理异常:将无效参数传递给认为无效参数致命的函数。

【问题讨论】:

    标签: c++ visual-studio-2015


    【解决方案1】:

    引用http://en.cppreference.com/w/cpp/chrono/c/localtime

    返回值

    成功时指向静态内部 std::tm 对象,否则为 NULL。该结构可以在 std::gmtime、std::localtime 和 std::ctime 之间共享,并且可以在每次调用时被覆盖。

    换句话说,你所有的struct tm *s 最终都指向同一个地方。你可能想要

    struct tm tm1 = *localtime(&timet_Now);
    

    如果您要坚持使用任何时间,请制作一份副本以供使用。

    肯尼·奥斯特罗姆(Kenny Ostrom)在 cmets 中提出了一个很好的观点。我没有处理 NULL 返回的情况并复制 NULL... 这不是一个好主意。

    struct tm * temp = localtime(&timet_Now);
    if (temp == nullptr)
    {
        // handle error. Throw exception, return, whatever, just don't run the next line 
    }
    struct tm tm1 = *temp;
    

    【讨论】:

    • 这就是为什么std::put_time 应该使用time_point 而不是tm*
    • 并检查 nullptr 返回,并考虑现有的 localtime_r 或 localtime_s 替代方案。
    • chronobest I've found so far is Howard Hinnant's answer here 寻找一个很好的方法
    • 哦......所以原因是在本地时间,那么。感谢您的解释、提示和链接。 (……又学到了一个)
    猜你喜欢
    • 2013-06-23
    • 2017-04-11
    • 2015-04-27
    • 2022-11-12
    • 2012-12-07
    • 2011-05-11
    • 1970-01-01
    • 2011-03-04
    • 2011-01-07
    相关资源
    最近更新 更多