12
#include <stdio.h>
#include <time.h>

int main()
{
     printf("Size of time_t is %lu bytes.\n", sizeof(time_t));
     time_t biggest = 0x7fffffffffffffff;   // line 1
     printf("time_t's wrap around will be a second after %s.\n", asctime(gmtime(&biggest)) );

     return 0;
}

In time.h is this the definition of time_t ?

typedef  __darwin_time_t   time_t

How to interpret it ? Since I don't have any idea, I used the sizeof function to find that time_t = 8 bytes.

Why line 1 is giving error then ? I'm getting this error

Segmentation fault: 11
  • Strange enough the standard does not seem to mandate a constant that contains the max value of `time_t`. For `int` and most other types it is described in [`limit.h`](http://pubs.opengroup.org/onlinepubs/009695399/basedefs/limits.h.html). `time_t` is described in [`sys/types.h`](http://pubs.opengroup.org/onlinepubs/7908799/xsh/systypes.h.html), but I can't find a macro that contains the max value (neigther in [`time.h`](http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/time.h.html). – Kijewski Jul 31 '12 at 20:20
  • Does it still segfault if you remove the first printf()? – Alexey Frunze Jul 31 '12 at 20:22
  • As Greg said, not all struct tm can hold time_t, when you use gdb you can see that the value returned by gmtime(&biggest) is always NULL, which explain the segFault. more on that on this URL : http://lists.apple.com/archives/darwin-dev/2008/Apr/msg00098.html – TOC Jul 31 '12 at 21:09
  • FYI, `sizeof` is an operator not a function. – Ernest Oct 22 '13 at 08:52
  • related: [Get the highest possible `gmtime()` for any architecture](http://stackoverflow.com/q/32045725/4279) – jfs Feb 27 '16 at 18:09
  • [%lu is not a correct way to print `size_t`](https://stackoverflow.com/q/940087/995714). Use `%zu` instead – phuclv Jan 01 '18 at 00:28
  • Misleading title. :( I came here looking for `sizeof(time_t)` and an explanation. – Unmanned Player Jun 27 '19 at 22:46

4 Answers4

8

Your call to gmtime() is probably returning NULL (it does on my Mac OS X system). When you pass this value to asctime(), you get an exception (since it expects a non-NULL pointer).

Not all time_t values can be represented in a struct tm, which is why gmtime() returns NULL in this case.

Greg Hewgill
  • 951,095
  • 183
  • 1,149
  • 1,285
  • Pardon but I'm still not clear on it. Does it implies that because the members of "struct tm" is of type int, although time_t in 8 bytes, it can only pass max value a type int can hold with setting MSB = 1 ? –  Aug 01 '12 at 05:18
  • 2
    Essentially, yes. The `tm_year` field of a `struct tm` (at least on the current version of Mac OS X) cannot hold the year number associated with the maximum value of `time_t` (when `time_t` is a 64 bit quantity). – Greg Hewgill Aug 01 '12 at 05:21
  • Greg nailed it! This is exactly what's happening on my 64-bit Linux box. I am kinda shocked that struct tm's members are int's on x86_64. – Man Vs Code Apr 14 '13 at 22:29
6

Although the size of time_t is 8, on a 64 bit platform there are implementation-defined limits hard-coded into the runtime that cannot be exceeded. When those limits are exceeded gmtime will return NULL with errno set to indicate the nature of the error. Your code fails to check for NULL return from gmtime, therefore asctime fails when it tries to dereference that null pointer. This is the hazard you risk when using idiomatic C and not checking return values from functions that can fail.

The Microsoft C gmtime on Windows 10 returns NULL with errno set to EINVAL when passed 32535291600. Even though one might think the theoretical maximum limit ought to be LLONG_MAX. Microsoft explicitly sets the limit to _MAX__TIME64_T + _MAX_LOCAL_TIME.

From ctime.h in Microsoft Visual Studio 2010 CRT sources:

#define _MAX__TIME64_T 0x793406fffi64 /* number of seconds from 00:00:00, 01/01/1970 UTC to 23:59:59. 12/31/3000 UTC */ 

Apple's gmtime function returns NULL and errno set to EOVERFLOW when it's passed 67768036191676800. The Apple implementation exhibits undefined behavior for all times where asctime() returns a string with more than 4 digits in the year because the C standard requires the function to return no more than 26 characters.

QwazyWabbit
  • 149
  • 2
  • 6
5

I looked into the Linux header files and found the following things:

/usr/include/time.h:
    typedef __time_t time_t;

/usr/include/bits/types.h:
    __STD_TYPE __TIME_T_TYPE __time_t

/usr/include/bits/typesizes.h
    #define __TIME_T_TYPE       __SLONGWORD_TYPE

/usr/include/bits/types.h:
    #define __SLONGWORD_TYPE    long int

So the size of time_t is long int. On a 64 bit machine, you probably get 8 bytes. Then I found that on my FreeBSD, which is 32 bit, it looked like this:

/usr/include/machine/_types.h:
    typedef __int32_t   __time_t;   

So the size is 32 bits.

Ernest
  • 880
  • 7
  • 9
3

The underlying type of time_t can be anything. It greatly depends on your system. Please refer to a similar question: What primitive data type is time_t?.

There is a link in the thread to the description of sys/types.h where it's stated that

time_t and clock_t shall be integer or real-floating types.

One more link to a good answer: https://stackoverflow.com/a/471287/276274

Community
  • 1
  • 1
Maksim Skurydzin
  • 10,301
  • 8
  • 40
  • 53