【问题标题】:Segfault when using time.h使用 time.h 时的段错误
【发布时间】:2014-03-23 13:03:26
【问题描述】:

好吧,我一直在尝试我所知道的一切来让这个程序停止崩溃,但我就是不明白为什么。我能够使用 ctime 将问题隔离到代码中,并且只是制作了一个小程序来演示出了什么问题。这段代码编译没有问题。

#include<iostream>
#include<ctime>

int main();
time_t getDay(time_t t);
int diffDay(time_t end,time_t begin);

int main()
{
    time_t curTime=time(NULL);  //Assign current time
    time_t curDay=getDay(curTime);  //Assign beginning of day
    time_t yesterday=curDay-16*60*60;   //Assign a time that's within yesterday
    time_t dif=diffDay(curTime,yesterday); //Assign how many days are between yesterday and curTime


    std::cout << "Cur Time: " << curTime << '\n'
            << "Cur Day: " << curDay << '\n'
            << "Yes Day: " << dif << '\n' << std::flush;

    char a;
    std::cin >> a; ///Program crashes after here.

    return 0;
}

///Get beginning of day that t is a part of
time_t getDay(time_t t)
{
    //Get current time
    struct tm* loctim=localtime(&t);

    if(loctim==0)
        return 0;

    //Set loctim to beginning of day
    loctim->tm_sec=0;
    loctim->tm_min=0;
    loctim->tm_hour=0;

    //Create a int from the new time
    int reval=mktime(loctim);

    //Free memory
    delete loctim;

    return reval;
}

///Calculate how many days are between begin and end
int diffDay(time_t end,time_t begin)
{
    time_t eDay=getDay(end); //Get beginning of day end is a part of
    time_t bDay=getDay(begin); //Get beginning of day begin is a part of
    time_t dif=(eDay-bDay)/(24*60*60); //Get how many days (86400 seconds)

    return dif;
}

这是我从调试中得到的一些文本。

调用堆栈

#0 77BC3242 ntdll!LdrLoadAlternateResourceModuleEx() (C:\Windows\system32\ntdll.dll:??)
#1 00000000 0x6d067ad3 in ??() (??:??)
#2 00000000 0x00000018 in ??() (??:??)
#3 77BC3080 ntdll!LdrLoadAlternateResourceModuleEx() (C:\Windows\system32\ntdll.dll:??)
#4 00000000 0x00000018 in ??() (??:??)
#5 77C60FCB ntdll!TpCheckTerminateWorker() (C:\Windows\system32\ntdll.dll:??)
#6 00000000 0x007f0000 in ??() (??:??)
#7 00000000 0x50000163 in ??() (??:??)
#8 00000000 0x00000018 in ??() (??:??)
#9 77C1AC4B ntdll!RtlReAllocateHeap() (C:\Windows\system32\ntdll.dll:??)
#10 00000000    0x007f0000 in ??() (??:??)
#11 00000000    0x50000163 in ??() (??:??)
#12 00000000    0x00000018 in ??() (??:??)
#13 77BC3080    ntdll!LdrLoadAlternateResourceModuleEx() (C:\Windows\system32\ntdll.dll:??)
#14 00000000    0x00000018 in ??() (??:??)
#15 769A9D45    msvcrt!malloc() (C:\Windows\syswow64\msvcrt.dll:??)
#16 769AF5D3    strcpy_s() (C:\Windows\syswow64\msvcrt.dll:??)
#17 769B2B18    open_osfhandle() (C:\Windows\syswow64\msvcrt.dll:??)
#18 00000000    0x00000018 in ??() (??:??)
#19 769B3C7D    msvcrt!_get_fmode() (C:\Windows\syswow64\msvcrt.dll:??)
#20 769BA6A0    msvcrt!_fsopen() (C:\Windows\syswow64\msvcrt.dll:??)
#21 00000000    0xc3458a06 in ??() (??:??)
#22 00000000    0x00000000 in ??() (??:??)

这里还有来自同一构建的另一个调用堆栈。

#0 77BE708C ntdll!RtlTraceDatabaseLock() (C:\Windows\system32\ntdll.dll:??)
#1 00000000 0x6ccdaf66 in ??() (??:??)
#2 00000000 0x00000000 in ??() (??:??)

这是一些特殊的构建选项吗?我正在使用 -std=c++0x 但决定在没有它的情况下尝试该程序,但它仍然崩溃。感谢您的帮助,我整天都在努力解决这个问题。

【问题讨论】:

  • 尝试使用 gdb 运行程序来定位问题所在。如果您对 gdb 不熟悉,您可以简单地在每行之后添加 cout 语句以在运行时跟踪程序。

标签: c++ segmentation-fault undefined-behavior localtime


【解决方案1】:

我认为问题出在这里:

  struct tm* loctim=localtime(&t);
  delete loctim;

localtime 返回一个指向静态缓冲区的指针。你不能释放它。这导致了“未定义的行为”。即某些数据被置于不一致的状态,并可能导致程序的另一个地方崩溃,这似乎与问题没有直接关系。

【讨论】:

  • 你当然不应该使用 C++ delete释放 C 函数的结果!
  • 哇,非常感谢。现在完全没有崩溃。我只阅读了 cplusplus.com 的解释,并没有真正看到任何地方,所以这导致我认为我必须自己释放它。也感谢您的建议。
  • @z121231211 我不知道 cplusplus.com 现在如何,但上次我检查它比 [cppreference.com](en.cppreference.com/w/cpp/chrono/c/localtime) 看起来不错而且也很清晰。跨度>
【解决方案2】:

找到此类问题的一个好方法是在 valgrind 下运行程序。它为您提供了有关问题所在的非常准确的信息 -

vlap:~/src $ valgrind ./a.out
==29314== Memcheck, a memory error detector
==29314== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==29314== Using Valgrind-3.9.0 and LibVEX; rerun with -h for copyright info
==29314== Command: ./a.out
==29314== 
==29314== Invalid free() / delete / delete[] / realloc()
==29314==    at 0x4C29E6C: operator delete(void*) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==29314==    by 0x400D2A: getDay(long) (test.cpp:44)
==29314==    by 0x400BEE: main (test.cpp:11)
==29314==  Address 0x59f5560 is 0 bytes inside data symbol "_tmbuf"
==29314==
==29314== Invalid free() / delete / delete[] / realloc()
==29314==    at 0x4C29E6C: operator delete(void*) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==29314==    by 0x400D2A: getDay(long) (test.cpp:44)
==29314==    by 0x400D4D: diffDay(long, long) (test.cpp:52)
==29314==    by 0x400C13: main (test.cpp:13)
==29314==  Address 0x59f5560 is 0 bytes inside data symbol "_tmbuf"
==29314==
==29314== Invalid free() / delete / delete[] / realloc()
==29314==    at 0x4C29E6C: operator delete(void*) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==29314==    by 0x400D2A: getDay(long) (test.cpp:44)
==29314==    by 0x400D5D: diffDay(long, long) (test.cpp:53)
==29314==    by 0x400C13: main (test.cpp:13)
==29314==  Address 0x59f5560 is 0 bytes inside data symbol "_tmbuf"
==29314==
Cur Time: 1395580379
Cur Day: 1395529200
Yes Day: 1
a
==29314==
==29314== HEAP SUMMARY:
==29314==     in use at exit: 0 bytes in 0 blocks
==29314==   total heap usage: 12 allocs, 15 frees, 1,846 bytes allocated
==29314==
==29314== All heap blocks were freed -- no leaks are possible
==29314==
==29314== For counts of detected and suppressed errors, rerun with: -v
==29314== ERROR SUMMARY: 3 errors from 3 contexts (suppressed: 3 from 3)

【讨论】:

  • 但在原始示例中意味着是基于 Windows 的平台,而 valgrind 不可用。
  • 你说的很对。我没有意识到 valgrind 在 Windows 上不可用。他们真的错过了。
  • 虽然 OP 的平台是 windows,但如果代码是跨平台的,我当然建议使用基本 Linux 发行版设置 VM,以便能够在以下环境下运行代码valgrind。
【解决方案3】:

你不能使用delete,它是一个c++ 操作符,来释放localtime() 的结果,它不使用c++ 内存管理。无论如何,您实际上不需要释放本地时间返回的值。

【讨论】:

    【解决方案4】:

    您可以使用 cmd 或终端在 cmd 上的文件中获取时间:echo %time% > time.txt 和在 linux 终端上:date > time.txt 您可以使用以下命令运行 commsnd:system(command) 而不是你阅读文件。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-10-18
      • 2016-05-04
      • 2017-08-02
      • 2010-10-07
      • 2021-07-03
      • 2011-11-29
      • 2020-01-28
      • 1970-01-01
      相关资源
      最近更新 更多