difference between time() and gettimeofday() and why does one cause seg fault

16,930

The short version

gettimeofday() requires a pointer to a struct timeval to fill with time data.

So, for example, you'd do something like this:

#include <sys/time.h>
#include <stdio.h>
int main() {  
    struct timeval tv;
    gettimeofday(&tv, NULL); // timezone should be NULL
    printf("%d seconds\n", tv.tv_secs);
    return 0;
}

The long version

The real problem is that gcc is automatically including vdso on your system, which contains a symbol for the syscall gettimeofday. Consider this program (entire file):

int main() {
  gettimeofday();
  return 0;
}

By default, gcc will compile this without warning. If you check the symbols it's linked against, you'll see:

ternus@event-horizon ~> gcc -o foo foo.c
ternus@event-horizon ~> ldd foo
        linux-vdso.so.1 =>  (0x00007ffff33fe000)
        libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f56a5255000)
        /lib64/ld-linux-x86-64.so.2 (0x00007f56a562b000)

You just happen to be using a function that has a defined symbol, but without the prototype, there's no way to tell how many command-line arguments it's supposed to have.

If you compile it with -Wall, you'll see:

ternus@event-horizon ~> gcc -Wall -o foo foo.c
foo.c: In function ‘main’:
foo.c:2:3: warning: implicit declaration of function ‘gettimeofday’ [-Wimplicit-function-declaration]

Of course, it'll segfault when you try to run it. Interestingly, it'll segfault in kernel space (this is on MacOS):

cternus@astarael ~/foo> gcc -o foo -g foo.c
cternus@astarael ~/foo> gdb foo
GNU gdb 6.3.50-20050815 (Apple version gdb-1822) (Sun Aug  5 03:00:42 UTC 2012)
[etc]

(gdb) run
Starting program: /Users/cternus/foo/foo
Reading symbols for shared libraries +.............................. done

Program received signal EXC_BAD_ACCESS, Could not access memory.
Reason: KERN_INVALID_ADDRESS at address: 0x0000000000000001
0x00007fff87eeab73 in __commpage_gettimeofday ()

Now consider this program (again, no header files):

typedef struct {
  long tv_sec;
  long tv_usec;
} timeval;

int main() {
  timeval tv;
  gettimeofday(&tv, 0);
  return 0;
}

This will compile and run just fine -- no segfault. You've provided it with the memory location it expects, even though there's still no gettimeofday prototype provided.

More information:

Can anyone understand how gettimeofday works?

Is there a faster equivalent of gettimeofday?

The POSIX gettimeofday specification

Share:
16,930
punstress
Author by

punstress

What would I do without my beloved Stack Overflow?!

Updated on June 04, 2022

Comments

  • punstress
    punstress almost 2 years

    I'm trying to measure the amount of time for a system call, and I tried using time(0) and gettimeofday() in this program, but whenever I use gettimeofday() it seg faults. I suppose I can just use time(0) but I'd like to know why this is happening. And I know you guys can just look at it and see the problem. Please don't yell at me!

    I want to get the time but not save it anywhere.

    I've tried every combination of code I can think of but I pasted the simplest version here. I'm new to C and Linux. I look at the .stackdump file but it's pretty meaningless to me.

    GetRDTSC is in util.h and it does rdtsc(), as one might expect. Now it's set to 10 iterations but later the loop will run 1000 times, without printf.

    #include <stdio.h>
    #include <time.h>
    #include "util.h"
    
    int main() {
    
        int i;
        uint64_t cycles[10];
    
        for (i = 0; i < 10; ++i) {
    
             // get initial cycles
             uint64_t init = GetRDTSC();
    
             gettimeofday(); // <== time(0) will work here without a seg fault.
    
             // get cycles after
             uint64_t after = GetRDTSC();   
    
             // save cycles for each operation in an array
             cycles[i] = after - init;
    
             printf("%i\n", (int)(cycles[i]));
        }  
    }
    
  • Barmar
    Barmar over 10 years
    It actually takes two arguments: timeval and timezone
  • Christian Ternus
    Christian Ternus over 10 years
    Right. "The use of the timezone structure is obsolete; the tz argument should normally be specified as NULL." linux.die.net/man/2/gettimeofday
  • punstress
    punstress over 10 years
    Wouldn't that cause a wrong-number-of-args error, not a seg fault? Since I don't want to save the time I tried using gettimeofday(0,0) and it gave the same result as gettimeofday(). Will adding &tv add cycles to the operation?
  • R.. GitHub STOP HELPING ICE
    R.. GitHub STOP HELPING ICE over 10 years
    @punstress: It would if you used the right compiler options (-Werror=implicit-function-declaration). Complain to the gcc developers that this option is still not default (this should always be an error, not a warning; it's invalid C and very dangerous).
  • Kninnug
    Kninnug over 10 years
    I think you also need to #include <sys/time.h>, right now the compiler assumes gettimeofday is a function that takes no arguments and returns an int, which is why it didn't complain, use -Wall to make it complain (for your own good).
  • punstress
    punstress over 10 years
    kninnug interesting idea, i had sys/time.h before and chgd it, so I tried changing it back just now and it failed seg fault. oh well i gtg so i'll look at this later.
  • punstress
    punstress over 10 years
    Would it matter if i added that i'm using cygwin not real linux?
  • Christian Ternus
    Christian Ternus over 10 years