访问struct中的struct的指针时出现分段错误

时间:2019-01-10 15:55:57

标签: c pointers struct segmentation-fault

我对结构体的指针也有疑问,该成员也具有结构体的指针。

浏览建议的类似问题,我发现了这一点:

Gramm Toolbox

人们建议注意结构的分配内存。

我认为这在我的代码中正确完成了。

typedef struct {
  int id_vec;
  float *vec_value;
} Vector;

typedef struct cluster{
  int id_cluster;
  float *centroid;
  Vector *patternInCluster; 
} Cluster;

int main(void){
  Cluster *cluster_ptr= malloc(3 * sizeof(Cluster));
  if (cluster_ptr==NULL){
    printf("NULL");
  }
  cluster_ptr->patternInCluster=malloc(2 * sizeof(Vector *));
  if (cluster_ptr->patternInCluster==NULL){
    printf("NULL");
    cluster_ptr->patternInCluster=NULL;
  }

  float p1[3]={0.0f,1.0f,2.0f};
  Vector *somePattern=malloc(2 * sizeof(Vector));
  somePattern[0].id_vec=1;
  somePattern[0].vec_value=p1;
  somePattern[1].id_vec=2;
  somePattern[1].vec_value=p1;
}

然后,我希望此语句有效:

cluster_ptr[1].patternInCluster[1]=somePattern[1];

但是它会编译并产生分段错误。

出乎意料的是,以下语句不会出现错误:

cluster_ptr[0].patternInCluster[1]=somePattern[1];

一个测试告诉我正确的结果(somePattern [1] ID和值)

我尝试使用gdb进行调试,但只能看到以下内容:

Program received signal SIGSEGV, Segmentation fault. 0x00005555555547fe in main () at test_struct.c:36 36 cluster_ptr[1].patternInCluster[1]=somePattern[1];

我错过一些分配错误吗?

3 个答案:

答案 0 :(得分:1)

这是因为您没有完全填充内容。

此行

cluster_ptr->patternInCluster=malloc(2 * sizeof(Vector *));

和说的一样

cluster_ptr[0].patternInCluster=malloc(2 * sizeof(Vector *));

实际上,鉴于cluster_ptr已被分配为3 Cluster,在您的代码中执行后者将更加清晰。

由于未给cluster_ptr[1].patternInCluster赋值,因此尝试取消引用将导致不确定的行为,但更有可能导致分段错误。

答案 1 :(得分:1)

您没有分配足够的内存:

cluster_ptr->patternInCluster=malloc(2 * sizeof(Vector *));

patternInCluster类型为Vector *的情况下,您应该分配内存以容纳类型Vector而不是Vector*的元素。

cluster_ptr->patternInCluster=malloc(2 * sizeof(Vector));

答案 2 :(得分:0)

您的问题不是访问结构内部的指针。您的问题是您如何使用malloc()

只有一个指针时,您只能分配一次:

int *pointer = (int* )malloc(sizeof(int));
*pointer = 1;
printf("*pointer:%d\n", *pointer);

当拥有指向指针的指针时,对**pointer_to_pointer使用一次malloc(),但是对*pointer_to_pointer也必须使用一次malloc():

int** pointer_to_pointer = (int** )malloc(sizeof(int*));
*pointer_to_pointer = (int* )malloc(sizeof(int));
**pointer_to_pointer = 2;
printf("**pointer:%d\n", **pointer_to_pointer);

如果在**pointer_to_pointer所指向的位置上有多个指针,则需要一个for循环才能为这些*pointer_to_pointer中的每一个分配内存。

for (unsigned int i = 0; i < 3; i++)
{
    *(pointer_to_pointer + i*sizeof(int)) = (int* )malloc(sizeof(int));
}
**(pointer_to_pointer + sizeof(int)) = 3;
**(pointer_to_pointer + 2UL*sizeof(int)) = 4;
printf("**(pointer_to_pointer + sizeof(int):%d\n", **(pointer_to_pointer + sizeof(int)));
printf("**(pointer_to_pointer + 2UL*sizeof(int):%d\n", **(pointer_to_pointer + 2UL*sizeof(int)));

您错误地认为Cluster *cluster_ptr= malloc(3 * sizeof(Cluster));将自动/神奇地为Cluster[0]Cluster[1]Cluster[2]分配内存。

您的语句实际上仅为Cluster[0]分配内存,但是足够大,可以容纳3个Cluster

修改后的代码如下所示:

#include <string.h>
#include <stdio.h>
#include <malloc.h>

typedef struct {
    int id_vec;
    float *vec_value;
} Vector;

typedef struct cluster{
    int id_cluster;
    float *centroid;
    Vector **patternInCluster;
} Cluster;

int main(void){

    Cluster **cluster_ptr = (Cluster **)malloc(sizeof(Cluster*));
    for (long unsigned int i = 0; i < 3; i++) {
        cluster_ptr[i] = (Cluster *)malloc(sizeof(Cluster));
        if (cluster_ptr[i]==NULL){
            printf("NULL");
        }

        cluster_ptr[i]->patternInCluster = (Vector **) malloc(sizeof(Vector*));
        for (long unsigned int j = 0; j < 3; j++) {
            (*cluster_ptr)->patternInCluster[j] = (Vector *) malloc(sizeof(Vector));
            if ((*cluster_ptr)->patternInCluster[j]==NULL){
                printf("NULL");
                (*cluster_ptr)->patternInCluster[j]=NULL;
            }
        }
    }



    float p1[3]={0.0f,1.0f,2.0f};
    Vector *somePattern= (Vector *) malloc(sizeof(Vector));
    somePattern[0].id_vec=1;
    somePattern[0].vec_value=p1;
    somePattern[1].id_vec=2;
    somePattern[1].vec_value=p1;

    cluster_ptr[1]->patternInCluster[1] = &somePattern[0];
    cluster_ptr[0]->patternInCluster[1] = &somePattern[1];
    cluster_ptr[1]->patternInCluster[0] = &somePattern[1];
    cluster_ptr[2]->patternInCluster[1] = &somePattern[0];

    printf("%d\n", cluster_ptr[1]->patternInCluster[1]->id_vec);
    printf("%d\n", cluster_ptr[0]->patternInCluster[1]->id_vec);
    printf("%d\n", cluster_ptr[1]->patternInCluster[0]->id_vec);
    printf("%d\n", cluster_ptr[2]->patternInCluster[1]->id_vec);

    return 0;
}
  • 在我的系统上,我刚刚进行编译,它可以无错误地构建和运行。