Search code examples
cstructdynamic-allocation

How to fix allocated memory from a struct hack in a different method?


I'm developing a driver in C for communication and the messages exchanged don't have a fixed size. The recommendation of communication bus is to use structs for multi-topics, which is also my case.

My 1st problem: I have to keep listening for new messages, and when I get one I have to process message data (it has a delay) and still listening for new messages.

1st solution: using thread when got new messages to process data.

My 2nd problem: Data in message can have multiple data of a struct, and my communicator requires using a struct to organize this multiple values.

2nd solution: using struct hack to allocate memory dynamic size of struct.

My current problem: when I'd pass my struct as argument to the thread, or any function, I'm loosing data structure and getting wrong values.

A short test which a made is:

typedef struct test{
    int size;
    int value[];
} test;

void allocation(test *v){
    test *aux = (test *)malloc(sizeof(test)+3*sizeof(int));
    int i;
    aux->value[0] = 2;
    aux->size = 3;
    aux->value[1] = 1;
    aux->value[2] = 5;
    printf("Teste1 %d\n",aux->size);
    for(i=0; i < aux->size; i++){
        printf("%d\n", aux->value[i]);
    }
    *v = *aux;
}

void cleanup(test *v){
    free(v);
}

int main(int argc, char *argv[]){
    test v;
    int i;

    allocation(&v);
    printf("Teste2 %d\n",v.size);
    for(i=0; i < v.size; i++){
        printf("%d\n", v.value[i]);
    }
    //cleanup(&v);
    return 0;
}

In this test I got right values in first print and wrong values in second (only v.size is giving a right value).

And my struct is a little more complex than that in test. My struct is like:

typedef struct test1{
    double v1;
    double v2;
} test1;

typedef struct test2{
    int size;
    test1 values[];
} test2;

Do you know how to fix my memory struct in that function, once I have all elements necessary to fix? Please, keep in mind that is desirable (not required) that I could also allocate multiple test2 data.


Solution

  • You are declaring v as non-pointer, meaning that the memory is already allocated for v when you declare it in main. Sending the reference to your allocation only copies the size correctly since it is not dynamically allocated. Correct way to do this would be to:

    • Declare your v as pointer

    • Make your allocation return test* (test* allocation())

    • Assign it to v in main. i.e. something like v = allocate()

    • And use v like a pointer from then on

    EDIT: Since OP wants this to work only as arguments, best way to go about it is using double pointer. Check the following code:

    typedef struct test{
        int size;
        int value[];
    } test;
    
    void allocation(test **v){
        test *aux = (test *)malloc(sizeof(test)+3*sizeof(int));
        int i;
        aux->value[0] = 2;
        aux->size = 3;
        aux->value[1] = 1;
        aux->value[2] = 5;
        printf("Teste1 %d\n",aux->size);
        for(i=0; i < aux->size; i++){
            printf("%d\n", aux->value[i]);
        }
        *v = aux;
    }
    
    void cleanup(test *v){
        free(v);
    }
    
    int main(int argc, char *argv[]){
        test **v;
        v = malloc (sizeof (test*));
        int i;
    
        allocation(v);
        printf("Teste2 %d\n",(*v)->size);
        for(i=0; i < (*v)->size; i++){
            printf("%d\n", (*v)->value[i]);
        }
        //cleanup(&v);
        return 0;
    }
    

    Please note that your cleanup will change too after this.