这段C代码是什么原因导致了分段错误?

3

编辑:感谢到目前为止的回答,至少我现在可以编译它了,但我仍然得到一个分段错误。

我使用以下命令进行编译:

gcc -g -O0 -I../include -L../ test.c -static -lrt

源代码如下:

#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;
}

我现在收到以下警告:
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’

分段错误肯定是由于我处理结构体的方式引起的。我很久以前就不再使用C语言了...

非常感谢, 马库斯


尝试运行 gcc -C -E foo.c 并查看 timespec 结构体的定义,如果有定义的话。至少在 Cygwin 上,我只有 timeval 而没有 timespec - csl
把-Wall选项加入编译器选项中。GCC会告诉你问题出在哪里 :) - Tim Post
5个回答

3

您的diff函数签名是timespec diff(timespec start, timespec end),它应该是struct timespec diff(struct timespec start, struct timespec end)


编辑 您的diff函数正在分配给未初始化的结构指针,您可能需要将其更改为以下内容。

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;
    }
}

谢谢,现在至少编译通过了。唯一剩下的问题是输出值为0秒和0.00000纳秒。肯定还有什么问题... - Marcus
1
@Marcus:确保你的printf语句正确--如果你使用%f而不是%ld,你将得到0.0000而不是正确的值。 - Chris Dodd

3
根据您的需求,您可能只需要像这样生成经过的时间: double t_ns = (double)(end.tv_sec - start.tv_sec) * 1.0e9 + (double)(end.tv_nsec - start.tv_nsec); // 以ns为单位获取经过的时间 另外,值得一提的是,我使用 - 在我尝试过的各种基于Linux的系统上,它似乎能够提供更好的精度和分辨率: clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &start); // ... 其他操作 ... clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &end);

0

你需要在 timespec 前面加上 struct 关键字。例如:

struct timespec diff(struct timespec start, struct timespec end);

0

我认为您想让diff()返回一个动态或静态分配的指针。

尝试以下建议(在评论中):

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 */
}

如果动态分配是禁忌,那么:
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;

你需要返回一个指针(无论如何分配),可以被调用者实际访问到。或者,将 *temp 变量设为全局变量。


0

你正在将它编译为C语言(gcc.c扩展名),但看起来你是在用C++编程(其中struct可以在声明变量时被提交)。

此外,在C语言中,我们通常不通过值传递结构体。

另一个提示是始终使用高警告级别进行编译,至少使用-Wall -pedantic,以便及早发现问题。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接