简体   繁体   中英

How to fill a dynamic array in another function (c)

I want to create a function, where I will scann elements (int) to an array and call this fuction in main, freeing memory also has to be in main.

int main () {
    int size = 0;
    int* arr = malloc (sizeof(int));
    char sign;
    int i = 0;
    do {
        scanf ("%d%c", &arr[i], &sign);
        i++;
    arr = realloc(arr, sizeof(int) * (i + 1));
    } while (sign != '\n');
    free(arr);
}

I 've tried to do this,

void initialize(int* arr) {
    char sign;
    int i = 0;
    do {
        scanf ("%d%c", &arr[i], &sign);
        i++;
        arr = realloc(arr, sizeof(int) * (i + 1));
    } while (sign != '\n');
}


int main () {
    int size = 0;
    int* arr = malloc (sizeof(int));
    
    initialize(arr);  
    free(arr);
  }

but I have an error

==140978== 1 errors in context 1 of 2:
==140978== Invalid free() / delete / delete[] / realloc()
==140978==    at 0x484B27F: free (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==140978==    by 0x1092A0: main (lol.c:21)
==140978==  Address 0x4a9a040 is 0 bytes inside a block of size 4 free'd
==140978==    at 0x484DCD3: realloc (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==140978==    by 0x109244: initialize (lol.c:10)
==140978==    by 0x109294: main (lol.c:19)
==140978==  Block was alloc'd at
==140978==    at 0x4848899: malloc (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==140978==    by 0x109284: main (lol.c:17)

Can I scann and fill a dynamic array in this way?

  1. You need to pass pointer to pointer.
  2. It is better to return size instead of relying on the sentinel values.
  3. Readin input is not good. It will not work. A single read will terminate the loop.
  4. Check the return value of scanf
  5. Check the return value of realloc
  6. Use objects not types in sizeof's
size_t initialize(int **arr) 
{
    size_t i = 0;
    int number;
    char line[100];
    while(fgets(line, sizeof(line), stdin) != NULL) 
    {
        if(sscanf(line, "%d", &number) == 1)
        {
            int *tmp;
            i++;
            tmp = realloc(*arr, sizeof(**arr) * i);
            if(tmp) 
            {
                *arr = tmp;
                (*arr)[i - 1] = number;
            }
            else 
            {
                /* error handling */
            }
        }
        else break;
    }
    return i;
}


int main (void) 
{
    size_t size;
    int *arr = NULL;
    
    size = initialize(&arr);  
    for(size_t i = 0; i < size; i++) printf("arr[%zu] = %d\n", i, arr[i]);
    free(arr);
}

https://godbolt.org/z/6zT47Kdxh

Return the new pointer like realloc does it.

int* initialize(int* arr) {
    char sign;
    int i = 0;
    do {
        scanf ("%d%c", &arr[i], &sign);
        i++;
        arr = realloc(arr, sizeof(int) * (i + 1));
    } while (sign != '\n');
    return arr;
}


int main () {
    int size = 0;
    int* arr = malloc (sizeof(int));
    
    arr = initialize(arr);  
    free(arr);
  }

realloc is able to work with NULL . You can improve your code.

int* initialize(int* arr) {
    char sign;
    int i = 0;
    do {
        arr = realloc(arr, sizeof(int) * (i + 1));
        scanf ("%d%c", &arr[i], &sign);
        i++;
    } while (sign != '\n');
    return arr;
}

int main () {
    int size = 0;
    int* arr = initialize(NULL);  
    free(arr);
  }

When passing a pointer to a function and invoking realloc on it, you are freeing the memory that the pointer points to. So after the initialize function finishes its execution, you are calling free on an invalid pointer (it was already freed). What you should probably do is manipulating with a double pointer:

void initialize(int** arr) {
    char sign;
    int i = 0;
    do {
        scanf ("%d%c", &(*arr)[i], &sign);
        i++;
        *arr = realloc(*arr, sizeof(int) * (i + 1));
    } while (sign != '\n');
}

And invoking this function would look like this:

initialize(&arr);

This way you are writing the newly allocated address with realloc by unreferencing the pointer, so that after initialize function exits you will see the reallocated address.

Also it is also a good practice to check the value of a pointer after calling malloc and realloc . See proper usage of realloc

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