【问题标题】:what is causing segmentation fault in c code, dynamic allocation accross functions是什么导致c代码中的分段错误,跨函数动态分配
【发布时间】:2012-10-23 21:38:39
【问题描述】:

我正在尝试动态分配结构数组并对它们执行操作,但我一直遇到分段错误。有人可以帮帮我吗?

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

void *malloc(size_t size);

typedef struct {
  double x;
  double y;
} coords;

struct figure {
  char fig_name[128];
  int coordcount, size_tracker;
  coords *pointer;
} fig;

void init_fig(int n, struct figure **point)
{
  printf("%u\n", sizeof(coords));
  point[n]->pointer = malloc(sizeof(coords) * 20);  <-------SEGFAULT
  if (point[n]->pointer == NULL){
    exit(-1);
  }
  point[n]->pointer[19].x = 2;
  point[n]->pointer[0].x = 1;
  point[n]->pointer[0].y = 2;
  point[n]->pointer[7].x = 100;
}

int main()
{
  int numfigs = 1;
  struct figure * point;
  point = malloc(sizeof(struct figure) * 16);
  point = &fig;
  point[1].coordcount = 1;
  init_fig(numfigs, &point);
  return 0;
}

我标记了第一个 seg 故障发生的位置,(使用 ddd)。我没有得到的是我可以在 main 中操作 point[1] 但不能在任何其他函数中操作。

【问题讨论】:

  • 这不是我的项目,它只是一个简短的测试文件,我一直在尝试找出为什么我会出现段错误

标签: c dynamic segmentation-fault


【解决方案1】:

我同意@Maxim Skurydin 的观点。 不过,我想更详细地解释您的错误。

读取您的init_fig 假设您传递struct figure **point 的参数实际上是指针数组struct figure。这个函数访问它的n'th 元素。

但是,在您的 main 中,您会执行其他操作。您分配了一个数组 struct figure,并且您的point 变量指向它的头部。然后你获取这个局部变量的地址并调用你的init_fig

这就是问题所在。 init_fig 假定您传递给它一个指针数组,而实际上这个“数组”仅包含一个元素:在 main 中声明的本地变量 point

编辑:

如何正确地做到这一点。

  1. 保持main不变,修复init_fig

这意味着实际上有一个figure 结构数组。手段 - 单个内存块,解释为一个后续结构的数组。

void init_fig(int n, struct figure *point)
{
  printf("%u\n", sizeof(coords));
  point[n].pointer = malloc(sizeof(coords) * 20);  <-------SEGFAULT
  if (point[n].pointer == NULL){
    exit(-1);
  }
  point[n].pointer[19].x = 2;
  point[n].pointer[0].x = 1;
  point[n].pointer[0].y = 2;
  point[n].pointer[7].x = 100;
}
  1. 保持init_fig 不变。修复main

这意味着我们实际上应该分配一个指针数组,每个这样的指针都应该指向一个分配的point结构。

int main()
{
  int numfigs = 1;
  struct figure ** point;
  point = malloc(sizeof(struct figure*) * 16);

  for (i = 0; i < 16; i++)
    point[i] = malloc(sizeof(struct figure));

  point[1].coordcount = 1;
  init_fig(numfigs, &point);
  return 0;
}

【讨论】:

  • hmm.. 你介意我问我如何正确地做到这一点吗?我的函数应该采用结构图*点吗?或者我应该在main中初始化一个结构图**点。抱歉,我对此有点陌生。
  • 好的,我做了选项 1,但现在我可以将东西分配给 point[n].pointer[233],它远远超出了分配的 20。为什么这样会起作用?我应该有段错误吗?点[n].pointer[233].x = 2; printf("%lf\n", point[n].pointer[233].x);
  • @user1787262 在分配的内存之外写入或读取是未定义的行为。如果您非常幸运,它会立即崩溃,如果您不太幸运,它会损坏重要数据并稍后崩溃。只是不要这样做。
  • 好的,谢天谢地你在那里解释了。我最初按照您上面描述的方式完成了我的程序,但是当我可以在分配的范围之外编写时感到困惑。但现在你解释了,我明白了,谢谢! @DanielFischer
【解决方案2】:

您分配内存并将指针存储在point 中,但是当您将&amp;fig 分配给它时,您忘记了该指针。

point = malloc(sizeof(struct figure) * 16);
point = &fig;

所以,你实际上是在尝试写fig[1],这没有意义。

【讨论】:

    【解决方案3】:
      struct figure * point;
      point = malloc(sizeof(struct figure) * 16);
    

    这里的point是指向堆中16个结构的内存的指针 但在下一行你已经这样做了

      point = &fig;
    

    所以它的内存泄漏和指向不再指向那个分配的区域

    还有init_fig应该是这样的

    void init_fig(int n, struct figure **point)
    

    是段错误的问题

    【讨论】:

      【解决方案4】:

      去掉这行point = &amp;fig;

      并修改函数:

      void init_fig(int n, struct figure *point)
      {
        ...
        point[n].pointer = (coords*) malloc(sizeof(coords) * 20);
        ...
      }
      

      因为你应该传递一个结构数组而不是一个指针数组。

      另外,向 init_fig 函数添加第三个参数,以便您可以传递要创建的点数组的大小。喜欢:

      void init_fig(int n, struct figure *point, int size)
          {
            ...
            point[n].pointer = (coords*) malloc(sizeof(coords) * size);
            ...
          }
      

      因此,使函数更具可重用性。

      同时修改对该函数的调用:

      init_fig(numfigs, &point); to init_fig(numfigs, point);
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-01-10
        • 2012-08-14
        • 1970-01-01
        • 2021-11-25
        • 1970-01-01
        • 2017-08-18
        • 1970-01-01
        相关资源
        最近更新 更多