What is causing the segmentation fault errors in this C code?
EDIT: Thanks for the answers so far, at least I can compile it now, but I still get a segmentation error.
For compilation I use the following line:
gcc -g -O0 -I../include -L../ test.c -static -lrt
Source code is as follows:
#include <sys/time.h>
#include <time.h>
#include <stdio.h>
struct timespec *diff(struct timespec *start, struct timespec *end);
int main()
{
struct timespec time1, time2;
int i;
int temp = 0;
clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &time1);
for (i = 0; i< 242000000; i++)
temp+=temp;
clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &time2);
printf("sec: %d, nsec: %f",diff(&time1,&time2)->tv_sec, diff(&time1,&time2)->tv_nsec);
//cout<<diff(time1,time2).tv_sec<<":"<<diff(time1,time2).tv_nsec<<endl;
return 0;
}
struct timespec *diff(struct timespec *start, struct timespec *end)
{
struct timespec *temp;
if ((end->tv_nsec-start->tv_nsec)<0) {
temp->tv_sec = end->tv_sec-start->tv_sec-1;
temp->tv_nsec = 1000000000+end->tv_nsec-start->tv_nsec;
} else {
temp->tv_sec = end->tv_sec-start->tv_sec;
temp->tv_nsec = end->tv_nsec-start->tv_nsec;
}
return temp;
}
I get now the following warning:
开发者_如何学编程test.c: In function ‘main’:
test.c:17: warning: format ‘%d’ expects type ‘int’, but argument 2 has type ‘__time_t’
test.c:17: warning: format ‘%f’ expects type ‘double’, but argument 3 has type ‘long int’
Segmentation fault is surely caused by my handling of the structures. It is quite a while ago that I last had to deal with C....
Many thanks, Marcus
Your diff function's signature is timespec diff(timespec start, timespec end)
, where it should be struct timespec diff(struct timespec start, struct timespec end)
.
EDIT Your diff function is assigning to an uninitialized struct pointer, you might want to change it to something like the following.
void diff(struct timespec *start, struct timespec *end,
struct timespec *result);
int main()
{
struct timespec time1, time2, result;
int i;
int temp = 0;
clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &time1);
for (i = 0; i< 242000000; i++)
temp+=temp;
clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &time2);
diff(&time1, &time2, &result);
printf("sec: %ld, nsec: %ld", (long int)result.tv_sec,
(long int)result.tv_nsec);
return 0;
}
void diff(struct timespec *start, struct timespec *end,
struct timespec * result)
{
if ((end->tv_nsec-start->tv_nsec)<0) {
result->tv_sec = end->tv_sec-start->tv_sec-1;
result->tv_nsec = 1000000000+end->tv_nsec-start->tv_nsec;
} else {
result->tv_sec = end->tv_sec-start->tv_sec;
result->tv_nsec = end->tv_nsec-start->tv_nsec;
}
}
Depending on your needs, you might just want to generate the elapsed time like this:
double t_ns = (double)(end.tv_sec - start.tv_sec) * 1.0e9 + (double)(end.tv_nsec - start.tv_nsec); // get elapsed time in ns
Also, FWIW, I use CLOCK_PROCESS_CPUTIME_ID
- it seems to give better accuracy and resolution on the various Linux-based systems that I've tried it on:
clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &start);
// ... stuff ... //
clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &end);
You have to add the struct keyword before the timespec's. E.g.
struct timespec diff(struct timespec start, struct timespec end);
You are compiling it as C (gcc
and .c
extension), but looks like you are coding in C++ (where struct
could be committed when declaring variables).
Also, in C we usually don't pass structures by value.
Another hint is to always compile with high warning level, at least -Wall -pedantic
, to catch problems early.
I think you want diff() to return either a dynamically or statically allocated pointer.
Try (suggestions in comments):
struct timespec *diff(struct timespec *start, struct timespec *end)
{
struct timespec *temp;
/* allocate temp to be sizeof(struct timespec) and zero it out */
temp = malloc(sizeof(struct timespec));
/* Of course, deal with malloc (or calloc) failing */
memset(tmp, 0, sizeof(struct timespec));
if ((end->tv_nsec-start->tv_nsec)<0) {
temp->tv_sec = end->tv_sec-start->tv_sec-1;
temp->tv_nsec = 1000000000+end->tv_nsec-start->tv_nsec;
} else {
temp->tv_sec = end->tv_sec-start->tv_sec;
temp->tv_nsec = end->tv_nsec-start->tv_nsec;
}
return temp;
/* Make sure caller frees the returned pointer */
}
If dynamic allocation is taboo, then:
static struct timespec temp;
/*zero it out, watch concurrency too! */
....
temp.tv_sec = end->tv_sec-start->tv_sec;
/* Make sure caller does NOT free (or modify) the pointer */
return temp;
You need to return a pointer there (however allocated) that can actually be reached by the caller. Or, make *temp global.
精彩评论