You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

访问point结构体数据时触发segfault的原因排查

段错误排查:访问结构体内部数据触发Segfault

在调用Calculate_values(&s)前的printf输出正常,但进入该函数后立即触发段错误,log1行从未输出,排除是Rpv函数调用导致的问题,怀疑是指针错误。

原代码

typedef struct point
{
    double *coord;
    double value;
} point;


typedef struct state
{
    void (*function)(point*, int);
    point *points; // p0, p1, p2, ...
    int dimentions; // number of points is always dimentions + 1
} state;

void Rpv(point *x, int dimentions)
{
    x->value = 0;

    for (int d = 0; d < dimentions - 1; d++)
        x->value += 100 * pow(x->coord[d + 1] - x->coord[d] * x->coord[d], 2) +
                          pow(1 - x->coord[d], 2);
}

void Calculate_values(state *s)
{
    for (int n = 0; n <= s->dimentions; n++)
    {
        printf("log (n: %d)\n", n);

        point p = s->points[0];

        printf("log1");

        s->function(p, s->dimentions);
        
        printf("log2\n");
    }
}


point minimisation(void (*function)(point*, int),
                   point initial_points[],
                   int dimentions)
{
    state s;
    s.points = initial_points;
    s.dimentions = dimentions;

    printf("[%lf, %lf] -> %lf\n", s.points[0].coord[0], s.points[0].coord[1], s.points[0].value);
    
    Calculate_values(&s);

    // ... more code

    return s.points[0];
}

int main()
{
    point initial_points[] = {
        {(double[]){3, 1}, 0}, // p1
        {(double[]){2, 0}, 0}, // p2
        {(double[]){0, 2}, 0}  // p3
    };

    point minimum = minimisation(Rpv, initial_points, 2);

    printf("minimum = %lf, @ (%lf, %lf)\n", minimum.value, minimum.coord[0], minimum.coord[1]);
    
    return 0;
}

输出结果

[3.000000, 1.000000] -> 0.000000
log (n: 0)
Segmentation fault (core dumped)

问题分析与修复

核心错误原因

  1. 函数参数类型不匹配
    state结构体中的function是接收point*类型参数的函数指针,但在Calculate_values调用时,你传递的是point类型变量p而非指针。这会导致编译器将结构体的值强行转换为无效指针地址,触发段错误。

  2. 循环逻辑错误
    当前循环每次都处理s->points[0],并未遍历所有dimentions+1个点,不符合代码注释中“遍历所有点”的预期。

修复后的Calculate_values函数

void Calculate_values(state *s)
{
    for (int n = 0; n <= s->dimentions; n++)
    {
        printf("log (n: %d)\n", n);

        // 直接获取当前点的指针,避免不必要的结构体拷贝
        point *p = &s->points[n];

        printf("log1");

        // 传递指针,匹配函数参数类型
        s->function(p, s->dimentions);
        
        printf("log2\n");
    }
}

额外建议

  • 编译时开启警告(如gcc -Wall),类型不匹配这类问题会被编译器直接提示,提前规避错误。
  • 你使用复合字面量初始化coord的方式是合法的C99特性,只要initial_points处于生命周期内,coord指针就是有效的,这部分无需修改。

内容的提问来源于stack exchange,提问作者Joe Allen

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.27 10:04:55