8

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]));
    }  
}
LSerni
  • 55,617
  • 10
  • 65
  • 107
punstress
  • 1,177
  • 2
  • 14
  • 26

1 Answers1

16

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

Community
  • 1
  • 1
Christian Ternus
  • 8,406
  • 24
  • 39
  • It actually takes two arguments: timeval and timezone – Barmar Oct 22 '13 at 21:28
  • Right. "The use of the timezone structure is obsolete; the tz argument should normally be specified as NULL." http://linux.die.net/man/2/gettimeofday – Christian Ternus Oct 22 '13 at 21:30
  • 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? – punstress Oct 22 '13 at 21:47
  • 2
    @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). – R.. GitHub STOP HELPING ICE Oct 22 '13 at 21:57
  • I think you also need to `#include `, 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). – Kninnug Oct 22 '13 at 21:58
  • 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 Oct 22 '13 at 22:00
  • Would it matter if i added that i'm using cygwin not real linux? – punstress Oct 23 '13 at 01:06
  • 1
    Performance-wise? Maybe. Implementation-wise? Nope. ["Cygwin consists of a library that implements the POSIX system call API in terms of Win32 system calls."](http://en.wikipedia.org/wiki/Cygwin) – Christian Ternus Oct 23 '13 at 01:31