简体   繁体   中英

returning struct with multiple variable length arrays from function in C

I have been searching for a solution for this for a while now. I think I know what is happening and what the solution should be, however I am not quite sure how to implement it.

I have a struct that contains two variable length arrays. These are to be filled within a function and returned to the calling function to do work with. The problem seems to be that any assignment of the variable length array becomes invalid when the called function goes out of scope. I would guess that a solution may be to allocate the memory on the heap and then free the memory once I am done with the struct in the calling function. A code example is given below

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 */
  .
  .
  .
}

First, you don't actually have two variable length arrays in your struct. It would be an error if you did. What you actually have is two pointers, each of which may point to the first element of an array of any size.

The problem you're having is that you're taking arrays created as local variables in the field function and assigning them (or more accurately pointers to their first elements) to the struct which is being returned. This means you're returning the address of local variables from the function. The lifetime of these locals end when the function exits, so the memory those pointers points to is invalid (and in fact the pointer values themselves are indeterminate ) and attempting to dereference those pointers triggers undefined behavior .

Also note that a variable length array cannot be initialized.

You need to dynamically allocate space for the A and B fields and write to those arrays. You can however use the existing local arrays to perform a memcpy if you don't want to copy individual members.

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;
}

local variables has their life-time - only inside the stack frame of their function.

if you want to create a variable and then use it outside the function you need to declare a variable with "bigger" scope like dynamically allocate it on the heap.

the life-time of heap variable is from the memory request (malloc) until 'free' or end of program.

so, if you want to return this struct it should be like this:

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);
    }

**don't forget to free this allocation

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM