difference between time() and gettimeofday() and why does one cause seg fault
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
Comments
-
punstress almost 2 years
I'm trying to measure the amount of time for a system call, and I tried using
time(0)
andgettimeofday()
in this program, but whenever I usegettimeofday()
it seg faults. I suppose I can just usetime(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, withoutprintf
.#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 over 10 yearsIt actually takes two arguments: timeval and timezone
-
Christian Ternus over 10 yearsRight. "The use of the timezone structure is obsolete; the tz argument should normally be specified as NULL." linux.die.net/man/2/gettimeofday
-
punstress over 10 yearsWouldn'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 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 over 10 yearsI think you also need to
#include <sys/time.h>
, right now the compiler assumesgettimeofday
is a function that takes no arguments and returns anint
, which is why it didn't complain, use-Wall
to make it complain (for your own good). -
punstress over 10 yearskninnug 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 over 10 yearsWould it matter if i added that i'm using cygwin not real linux?
-
Christian Ternus over 10 yearsPerformance-wise? Maybe. Implementation-wise? Nope. "Cygwin consists of a library that implements the POSIX system call API in terms of Win32 system calls."