Requiem
Requiem

Reputation: 21

C, malloc an array inside a struct[]

I have a struct[4] with inside a pointer. I have to malloc this pointer for all the 4 structs

//Here a simplification of my code that produces the same error:

typedef struct{
    int *val;
}test_T;

void testAllocSingle(test_T *in){
    in->val = (int *)calloc(10, sizeof(int));
}

void testAlloc(test_T *in){
    int i = 0;
    for (i=0; i<4; i++){
        testAllocSingle(&(in[i]));
    }
}

void main(void){
    test_T a[4];
    test_T b[4];
    testAlloc(a);
    testAlloc(b);
    memcpy(b, a, 4*10*sizeof(int));
    //FATAL RUN-TIME ERROR: Array argument too small (16 bytes).  Argument    must contain at least 160 bytes (160 elements).
}

My allocated array is not visible to main. I'm doing something wrong in passing variables, can anyone tell me where?

Thanks

Upvotes: 0

Views: 174

Answers (5)

Requiem
Requiem

Reputation: 21

thank you all for the answers. Maybe I simplified this example too much. Unfortunately, there are many other variables in the structure in question

An example closer to reality can be this:

#define    MALLOC_SIZE    (10) //in the original code is a variable
typedef struct{
    int size;
    int x;
    double y;
    char z[32];
    int *val;
}test_T;

void setSize(test_T *in){
    int i = 0;
    for (i=0; i<4; i++){
        in[i].size = 0;
        in[i].size += sizeof(int);//size
        in[i].size += sizeof(int);//x
        in[i].size += sizeof(double);//y
        in[i].size += (sizeof(char)*32);//z
        in[i].size += (sizeof(int)*MALLOC_SIZE);
    }
}

void testAllocSingle(test_T *in){
    in->val = (int *)calloc(MALLOC_SIZE, sizeof(int));
}

void testAlloc(test_T *in){
    int i = 0;
    for (i=0; i<4; i++){
        testAllocSingle(&(in[i]));
    }
}

int main(void){
    int tot_size = 0;

    test_T a[4];
    test_T b[4];

    testAlloc(a);
    testAlloc(b);

    setSize(a);
    tot_size = a[0].size + a[1].size + a[2].size + a[3].size;

    memcpy(b, a, tot_size);
    //FATAL RUN-TIME ERROR: Array argument too small (16 bytes).  Argument    must contain at least 160 bytes (160 elements).
    return 0;
}

Copying everything "manually" remains possible but more inconvenient. The strange thing is that I only have the problem if I compile and execute the code with NI CVI. If I compile and execute the code with Eclipse+MinGW I haven't this error

Upvotes: 0

the busybee
the busybee

Reputation: 12600

The data structures you have before memcpy() look like this in RAM:

Picture

Each of the rectangles is a continous block of memory. It can be in any place, not necessarily in a special order, and not in adjacent places.

When you do

b[i] = a[i];

then the storage pointed to by b[i] will be "leaked", that means you lose the reference to it and you can't free it. Both b[i] and a[i] will point to the same array of 10 ints.

When you do

memcpy(b, a, sizeof a);

then all storage pointed to by b[0] to b[3] will be leaked.

To copy all ints from a to b, you could use @Barmar's loop, or this one:

for (int i = 0; i < 4; i++) {
    for (int j = 0; j < 10; j++) {
        b[i].val[j] = a[i].val[j];
    }
}

Upvotes: 0

Sarath Padakandla
Sarath Padakandla

Reputation: 20

Another easiest way is copy with for() instead of memcpy to avoid confusion,

for(i=0;i<4;i++){
b[i] = a[i];
}

Upvotes: 1

Barmar
Barmar

Reputation: 780673

It's not clear what you're trying to copy, but 4 * 10 * sizeof(int) is not correct in any case. You haven't allocated any single contiguous block that size.

If you want to copy just the array of structs, which just copies the pointers to the array, it's:

memcpy(b, a, 4 * sizeof(test_t));

Note that this causes a memory leak, because you never freed the memory that was allocated in b.

If you want to copy each of the arrays of ints, it's

for (int i = 0; i < 4; i++) {
    memcpy(b[i].val, a[i].val, 10 * sizeof(int));
}

This doesn't leak anything, because it's just copying the integers in the arrays, not changing the pointers.

Upvotes: 2

Renat
Renat

Reputation: 8962

You're calculating size of a and b incorrectly. a and b are 4-elements array of test_T, each of test_T has a pointer to int array. a and b are not contiguous memory with size 4 * 10 * sizeof(int).

You might need instead:

memcpy(b, a, sizeof(a));

Upvotes: 1

Related Questions