访问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)
问题分析与修复
核心错误原因
函数参数类型不匹配
state结构体中的function是接收point*类型参数的函数指针,但在Calculate_values调用时,你传递的是point类型变量p而非指针。这会导致编译器将结构体的值强行转换为无效指针地址,触发段错误。循环逻辑错误
当前循环每次都处理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
相关产品推荐
相关产品推荐

