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

C语言聚类初始化函数出现SIGSEGV内存访问错误求助

排查k聚类初始化函数中的SIGSEGV错误

问题描述

编写基于点间距离选择初始中心的k聚类初始化函数时,执行*p_discard_set[i] = id;触发interrupted by signal 11: SIGSEGV错误,而*p_discard_set[0] = i;能正常执行,且k>2,确认数组无越界情况,需要排查错误原因。

相关代码

初始化函数代码

int *inizialize_centroids(int *p_dataset, int d, int k, int **p_discard_set) {

    int* centroids = (int*) malloc(k*((2*d)+1)*sizeof(int)), *point_to_compare = (int*) malloc(d*sizeof(int)),
    *cluster_point = (int*) malloc(d*sizeof(int));
    float* distance = (float*) malloc(2*k*sizeof(float));
    if(centroids == NULL || point_to_compare == NULL || cluster_point == NULL || distance == NULL){
        printf("Something went wrong in inizialize_centroids(), memory allocation failed! (row 94/95)");
        exit(1);
    }

    centroids[0]=1;
    for(int i = 1; i < d; i++){
        centroids[i] = p_dataset[i];
        centroids[i+d] = pow(p_dataset[i],2);
    }

    *p_discard_set[0] = 1;
    *p_discard_set[1] = p_dataset[0];
    memcpy(cluster_point, &p_dataset[0], (d + 1)*sizeof(int));

    int j;
    int i = 1;
    int t;
    while (i < k){
        
        j = 0;
        while(j < 2*CHUNK ){
            memcpy(point_to_compare, &p_dataset[j/2 * (d + 1)], (d + 1) * sizeof(int));
            
            distance[j] = (float) point_to_compare[0];
            j++;
            distance[j] = compare(cluster_point, point_to_compare, i, d);
            j++;
        }

        int id = (int) distance[0];
        float max = distance[1];

        j = 0;
        while (j < 2* CHUNK){
            if(distance[j+1] > max){
                max = distance[j+1];
                id = distance[j];
            }
            j+=2;
        }

        i++;

        *p_discard_set[0] = i;
        *p_discard_set[i] = id; // 触发错误的行

        [....]

    }

    return centroids;
}

main函数调用代码

int *discard_set = (int*) malloc((k + 1) * sizeof(int)), *compressed_set = (int*) malloc(sizeof(int)), *retained_set = (int*) malloc(sizeof(int));
// discard_set 结构: [n, id_1, ... , id_n]

if(discard_set == NULL || compressed_set == NULL || retained_set == NULL){
    printf("Something went wrong in main(), memory allocation failed! (row 39)");
    exit(1);
}

int* centroids = inizialize_centroids(dataset, d, k, &discard_set);

错误原因

核心问题是运算符优先级:数组下标运算符[]的优先级高于解引用运算符*。

  • *p_discard_set[i] 实际等价于 *(p_discard_set[i]):先取p_discard_set的第i个元素(但p_discard_set是指向单个指针的指针,仅p_discard_set[0]有效),再解引用这个不存在的指针,直接导致内存访问越界,触发SIGSEGV。
  • 而*p_discard_set[0]能运行是巧合:它等价于*(p_discard_set[0]),也就是discard_set[0],刚好访问的是合法内存,但这种写法本身是错误的,存在隐藏风险。

修复方案

将所有涉及*p_discard_set的下标访问改为先解引用指针,再访问数组下标,即用(*p_discard_set)[index]替代*p_discard_set[index]:

修改后的关键代码:

// 初始化部分
(*p_discard_set)[0] = 1;
(*p_discard_set)[1] = p_dataset[0];

// 循环内赋值部分
(*p_discard_set)[0] = i;
(*p_discard_set)[i] = id;

这样先通过(*p_discard_set)得到main函数中分配的discard_set数组指针,再访问其下标,就能保证内存访问合法,解决段错误问题。

内容的提问来源于stack exchange,提问作者Luca Lotifi

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.12 00:10:36