释放动态分配数组后的C分段错误

释放动态分配数组后的C分段错误,c,arrays,struct,segmentation-fault,C,Arrays,Struct,Segmentation Fault,我试图创建动态分配的集群阵列,其中每个集群都有自己的动态分配的点阵列 typedef struct Point { int ID; //each point has some ID and XY coordinates int X; int Y; }Point; typedef struct Cluster { int size; //how many points can cluster hold int count; //how m

我试图创建动态分配的集群阵列,其中每个集群都有自己的动态分配的点阵列

typedef struct Point
{
    int ID; //each point has some ID and XY coordinates
    int X;
    int Y;
}Point;

typedef struct Cluster
{
    int size;      //how many points can cluster hold
    int count;     //how many points cluster actually holds
    Point *points; //dynamically allocated array of points
}Cluster;
我能够初始化群集阵列并使用此函数填充它:

void fill_array(Cluster **arr, int how_many_clusters)
{
    *arr = (Cluster *)malloc(sizeof(Cluster) * how_many_clusters);

    for(int i = 0; i < how_many_clusters; i++)
    {
        Point point;
        point.ID = i;
        point.X = i * 2;
        point.Y = i * 3;
        (*arr)[i].size = 1;
        (*arr)[i].count = 1;
        (*arr)[i].points = (Point *)malloc(sizeof(Point));
        (*arr)[i].points[i] = point;
    }
}
当我编译并运行这个程序时,它在
free
ing的第二次迭代中崩溃,出现了分段错误。在过去的两天里,我一直在互联网上搜寻,但没有发现我做错了什么。 有人能指出我看不出的错误在哪里吗

(*arr)[i].points[i] = point;
这看起来不对。应该是

(*arr)[i].points[0] = point;
以下位:

    (*arr)[i].points = (Point *)malloc(sizeof(Point));
    (*arr)[i].points[i] = point;

没有分配正确的内存量
i
将是一些大于零的数字,但您只为一个
分配了空间。你正在粉碎你的堆,随后将发生崩溃。

没有必要强制执行malloc的返回,这是不必要的。请参阅:
malloc
返回与任何指针兼容的
void*
。石膏只能使水变得浑浊。只需分配指针
,然后对取消引用的指针调用
sizeof
,例如:

(*arr)[i].points = malloc (sizeof *(*arr)[i].points);
虽然分配语句正确,但它完全无法验证分配是否成功,相反,请检查
malloc
返回的值是否为
NULL
,例如

         if (!((*arr)[i].points = malloc (sizeof *(*arr)[i].points))) {
            perror ("malloc failed - points");
            exit (EXIT_FAILURE);
        }
    if (!(*arr = malloc (sizeof **arr * nclusters))) {
        perror ("malloc failed - nclusters");
        exit (EXIT_FAILURE);
    }
        *(*arr)[i].points = point;  /* copy struct to allocated memory */
分配
*arr
时也一样,例如

         if (!((*arr)[i].points = malloc (sizeof *(*arr)[i].points))) {
            perror ("malloc failed - points");
            exit (EXIT_FAILURE);
        }
    if (!(*arr = malloc (sizeof **arr * nclusters))) {
        perror ("malloc failed - nclusters");
        exit (EXIT_FAILURE);
    }
        *(*arr)[i].points = point;  /* copy struct to allocated memory */
(注意:
有多少个集群被缩短为
nclusters
,我们不是在写小说)

你的主要问题是:

        (*arr)[i].points[i] = point;
您只为一个
结构
分配内存,因此
点[i]
毫无意义。您分配了
sizeof(Point)
——您认为有多少个

由于您的目标是将
复制到指针持有的地址处新分配的内存块
(*arr)[i]。点
,“如何访问(或设置)指针引用(例如指向)的值?”(答案:,您取消指针引用以获得值)

这就是你在这里需要做的。没有额外的
[…]
附加到解除引用
(*arr)[i]的末尾。点
,只需用一元
'*'
解除引用即可,例如

         if (!((*arr)[i].points = malloc (sizeof *(*arr)[i].points))) {
            perror ("malloc failed - points");
            exit (EXIT_FAILURE);
        }
    if (!(*arr = malloc (sizeof **arr * nclusters))) {
        perror ("malloc failed - nclusters");
        exit (EXIT_FAILURE);
    }
        *(*arr)[i].points = point;  /* copy struct to allocated memory */
将这些部分放在一起,您可以执行以下操作:

#include <stdio.h>
#include <stdlib.h>

typedef struct {
    int ID; //each point has some ID and XY coordinates
    int X;
    int Y;
} Point;

typedef struct {
    int size;      //how many points can cluster hold
    int count;     //how many points cluster actually holds
    Point *points; //dynamically allocated array of points
} Cluster;

void fill_array (Cluster **arr, int nclusters)
{
    if (!(*arr = malloc (sizeof **arr * nclusters))) {
        perror ("malloc failed - nclusters");
        exit (EXIT_FAILURE);
    }
    for (int i = 0; i < nclusters; i++)
    {
        Point point;
        point.ID = i;
        point.X = i * 2;
        point.Y = i * 3;
        (*arr)[i].size = 1;
        (*arr)[i].count = 1;
        if (!((*arr)[i].points = malloc (sizeof *(*arr)[i].points))) {
            perror ("malloc failed - points");
            exit (EXIT_FAILURE);
        }
        *(*arr)[i].points = point;  /* copy struct to allocated memory */
    }
}

int main (void) {

    Cluster *clusters;
    int clusters_count = 20;

    fill_array (&clusters, clusters_count);

    for(int i = 0; i < clusters_count; i++)
    {
        free(clusters[i].points); //crash point
        clusters[i].points = NULL;
    }
    free (clusters);

    return 0;
}
始终确认已释放所有已分配的内存,并且没有内存错误


仔细检查一下,如果您还有其他问题,请告诉我。

没有,但它有效。我尝试了
printf()
在每一行进行调试。崩溃点ts实际上位于
main
@user3670471如果它没有在这条线上崩溃,并不意味着这条线本身就正常。用
0
替换第二个
i
,它就会工作。是的,现在我看到问题了。非常感谢。
(*arr)[i]。点[i]=点写入超出范围。您只为一个点分配了空间