carrayspointersstructdynamic-allocation

Remove element from dynamic array of structure


I'm working in C

I have a struct called Entity and I create a dynamic array of that struct. Then I try to remove one element from the array but I don't get the behaviour I want.

Here is the code I'm using:

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

typedef struct Entity
{
    int x, y;
    int velX, velY;
}Entity;

int remove_element(Entity** array, int sizeOfArray, int indexToRemove)
{
    int i;

    printf("Beginning processing. Array is currently: ");
    for (i = 0; i < sizeOfArray; ++i)
        printf("%d ", (*array)[i].x);
    printf("\n");

    Entity* temp = malloc((sizeOfArray - 1) * sizeof(Entity)); // allocate an array with a size 1 less than the current one

    memmove(
            temp,
            *array,
            (indexToRemove+1)*sizeof(Entity)); // copy everything BEFORE the index

    memmove(
            temp+indexToRemove,
            (*array)+(indexToRemove+1),
            (sizeOfArray - indexToRemove)*sizeof(Entity)); // copy everything AFTER the index


    printf("Processing done. Array is currently: ");
    for (i = 0; i < sizeOfArray - 1; ++i)
        printf("%d ", (temp)[i].x);
    printf("\n");

    free (*array);
    *array = temp;
    return 0;

}

int main()
{
    int i;
    int howMany = 20;

    Entity* test = malloc(howMany * sizeof(Entity*));

    for (i = 0; i < howMany; ++i)
        (test[i].x) = i;

    remove_element(&test, howMany, 14);
    --howMany;

    return 0;
}

And the output I get :

Beginning processing. Array is currently: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
Processing done. Array is currently: 0 1 2 3 4 1866386284 6 7 8 9 10 11 12 13 15 16 17 18 19

Then the program crashes at the free (*array); line. I want my second line to be 0 1 2 3 4 5 6 7 8 9 10 11 12 13 15 16 17 18 19.

How could I solve my problem ?


Solution

  • First thing you have allocated memory space for holding 20 Enity*. Then you have dereferenced it (and the value it contained is indeterminate). This is undefined behavior. And all story ends here.

    But let's analyze what you mostly wanted.

    Entity* test = malloc(howMany * sizeof(Entity));
                                           ^^^^^^^
    

    is what you wanted. Because only if you do this you will get the member elements x and so on.

    Also if you are considering 0 indexing then the memmove calls should be

    memmove(temp, *array, (indexToRemove)*sizeof(Entity)); 
    memmove(temp+indexToRemove, (*array)+(indexToRemove+1), 
                (sizeOfArray - indexToRemove - 1)*sizeof(Entity)); 
    

    These two changes will be enough to solve the problems you are facing and realizing the correct behavior. (If this is all there is in your code).

    Also as per standard the main() should be declared like this in case it doesn't take any parameter int main(void). Free the dynamically allocated memory when you are done working with it. Also you should check the return value of malloc - in case it fails it returns NULL and you should handle that case.