从 C 中的函数返回具有多个可变长度数组的结构

returning struct with multiple variable length arrays from function in C

我一直在寻找解决方案。我想我知道发生了什么以及解决方案应该是什么,但是我不太确定如何实施它。

我有一个包含两个可变长度数组的结构。这些将在函数中填充并返回给调用函数进行处理。 问题似乎是当被调用函数超出范围时,可变长度数组的任何分配都变得无效。我猜想一个解决方案可能是在堆上分配内存,然后在完成调用函数中的结构后释放内存。下面给出代码示例

struct fields {
  int n;
  double * A;
  double * B;
};

struct fields field() {
  int n = 4;
  double A[n] = { 1, 2, 3, 4 };
  double B[n] = { 1, 2, 3, 4 };

  struct fields field;
  field.n = n;
  field.A = A;
  field.B = B;
  /* field can be accessed with n, A, B set properly */
  return field;
}

double calling_function() {
  struct fields field1 = field();
  /* field1 contains n but A and B have not returned */
  .
  .
  .
}

局部变量有其生命周期 - 仅在其函数的堆栈帧内。

如果你想创建一个变量,然后在函数之外使用它,你需要声明一个具有“更大”范围的变量,比如在堆上动态分配它。

堆变量的生命周期是从内存请求(malloc)到'free'或程序结束。

所以,如果你想 return 这个结构应该是这样的:

struct fields *field() {


    struct fields *field = (struct fields *)malloc(sizeof(struct fields));
    if (NUUL == filed)
    {
        return (NULL);
    }

    field->n = 4;

    field->A = (double *)malloc(sizeof(double) * n);
    //check if malloc fail

    field->B = (double *)malloc(sizeof(double) * n);
    //check if malloc fail

    //assign A and B their values

      return (field);
    }

**不要忘记释放这个分配

free(field->A);
free(field->B);
free(field);

首先,您的结构中实际上没有两个可变长度数组。如果你这样做了,那将是一个错误。你实际上拥有的是两个指针,每个指针都可能指向任意大小数组的第一个元素。

您遇到的问题是,您将在 field 函数中创建为局部变量的数组分配给返回的结构(或更准确地说是指向其第一个元素的指针) .这意味着您要从函数返回局部变量的地址。这些局部变量的生命周期在函数退出时结束,因此这些指针指向的内存是无效的(实际上指针值本身是 不确定)并且尝试取消引用这些指针会触发 undefined behavior.

另请注意,可变长度数组无法初始化。

您需要为 AB 字段动态分配 space 并写入这些数组。但是,如果您不想复制单个成员,则可以使用现有的本地数组来执行 memcpy

struct fields field() {
  double A[4] = { 1, 2, 3, 4 };
  double B[4] = { 1, 2, 3, 4 };

  struct fields field;
  field.n = 4;
  field.A = malloc(sizeof A);
  field.B = malloc(sizeof B);
  memcpy(field.A, A, sizeof A);
  memcpy(field.B, B, sizeof B);
  return field;
}