malloc of an array within a struct

问题内容:

I have the following code declaring a struct:

typedef struct variable_array{
    int length;
    BUCKET * array;
}VARIABLE_ARRAY;

typedef struct bucket{
    int Hash;
    int KeyValue;
    char Data[MAX_INPUT];
    char Key[MAX_INPUT];
}BUCKET;

I am then declaring the array with the following code:

VARIABLE_ARRAY varArray[Width];

Then to create the array withing the VARIABLE_ARRAY i am using this:

varArray[hash].array = malloc(varArray[hash].length  * sizeof(BUCKET));

However, the malloc for some reason never creates more than one element in the array. Even when the length is changed. I am not sure on what steps to take to fix this issue.

问题评论:

4  
However, the malloc for some reason never creates more than one element in the array. How do you know?
1  
“using the debugging tool built in to CLion” what is that actually telling you? are you certain that it will show a dynamically allocated array differently to a single value?
2  
What you say is not plausable. malloc will just do as told, or return null upon failure. Your debugging tool will just show a pointer, but not how many elements there were allocated in the memory pointed to.
1  
@Sean – How exactly are you gleaning it from the debugging tools? malloc would return the address of the first item. It would look the same for one or many items. But the amount of memory is vastly different.
1  
@Sean then the first part of my comment applies here. What makes you think that malloc for some reason never creates more than one element in the array?

答案:

答案1:

There must be something wrong with what you are passing to malloc, and that something can not be pointed out and/or fixed, unless you don’t show us the full code.

malloc won’t do anything funny unless you do something funny with it.
Its time to look at values you are setting:
Width, hash, and varArray[hash].length

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

#define WIDTH       5
#define MAX_INPUT   32

typedef struct bucket {
    int Hash;
    int KeyValue;
    char Data[MAX_INPUT];
    char Key[MAX_INPUT];
} BUCKET;

typedef struct variable_array {
    int length;
    BUCKET * array;
} VARIABLE_ARRAY;

VARIABLE_ARRAY varArray[WIDTH];

int main(void) 
{
    int i = 0, hash = 5;

    for(i = 0; i < hash ; i++)
    {
        varArray[i].array = malloc(sizeof(BUCKET));
        if(varArray[i].array == NULL)
        {
            printf("\nWhoa! Out of memory, returning!");
            return -1;
        }
        varArray[i].array->Hash = i + 10;
        varArray[i].array->KeyValue = i + 15;
        sprintf(varArray[i].array->Data, "Data Instance: %1d", i);
        sprintf(varArray[i].array->Key, "Key Instance: %1d", i);
    }

    for(i = 0; i < hash ; i++)
    {
        printf("\nHash = %d, KeyValue = %d, %s, %s", varArray[i].array->Hash, varArray[i].array->KeyValue, varArray[i].array->Data, varArray[i].array->Key);
    }

    for(i = 0; i < hash ; i++)
    {
        free(varArray[i].array);
        varArray[i].array = NULL;
    }

    return 0;
}

The output it produces is:

Hash = 10, KeyValue = 15, Data Instance: 0, Key Instance: 0
Hash = 11, KeyValue = 16, Data Instance: 1, Key Instance: 1
Hash = 12, KeyValue = 17, Data Instance: 2, Key Instance: 2
Hash = 13, KeyValue = 18, Data Instance: 3, Key Instance: 3
Hash = 14, KeyValue = 19, Data Instance: 4, Key Instance: 4

which seems as expected.

As you can see, varArray[hash].length is what I didn’t use at all, So, either I don’t understand your design, or its not needed. I’ll let you decide that.

Probable cause of trouble:

You insisted that the varArray[hash].length was set to 2, so the malloc should have allocated a chunk from heap which is of the size equal to twice of sizeof(BUCKET).
Its just that you have one pointer to access two consecutive (logical!) blocks of similar data types.

So, if I add to my code to what it looks like below (Which is very ugly and something which should be avoided for the sake of readability, BTW)

printf("\n_______");
printf("\nTake 2!\n");

varArray[0].length = 2;
varArray[0].array = malloc(varArray[0].length * sizeof(BUCKET));
if(varArray[0].array == NULL)
{
    printf("\nWhoa! Out of memory, returning!");
    return -1;
}
varArray[0].array->Hash = 10;
varArray[0].array->KeyValue = 15;
sprintf(varArray[0].array->Data, "Data Instance: %1d", 0);
sprintf(varArray[0].array->Key, "Key Instance: %1d", 0);

printf("\nHash = %d, KeyValue = %d, %s, %s", varArray[0].array->Hash, varArray[0].array->KeyValue, varArray[0].array->Data, varArray[0].array->Key);

(varArray[0].array+sizeof(BUCKET)+sizeof(varArray[0].array->Hash))->Hash = 11;
(varArray[0].array+sizeof(BUCKET)+sizeof(varArray[0].array->KeyValue))->KeyValue = 16;
sprintf((varArray[0].array+sizeof(BUCKET)+sizeof(varArray[0].array->Data))->Data, "Data Instance: %1d", 1);
sprintf((varArray[0].array+sizeof(BUCKET)+sizeof(varArray[0].array->Key))->Key, "Key Instance: %1d", 1);

printf("\nHash = %d, KeyValue = %d, %s, %s", (varArray[0].array+sizeof(BUCKET)+sizeof(varArray[0].array->Hash))->Hash, (varArray[0].array+sizeof(BUCKET)+sizeof(varArray[0].array->KeyValue))->KeyValue, (varArray[0].array+sizeof(BUCKET)+sizeof(varArray[0].array->Data))->Data, (varArray[0].array+sizeof(BUCKET)+sizeof(varArray[0].array->Key))->Key);

free(varArray[0].array);
varArray[0].array = NULL;

It generates an output:

Hash = 10, KeyValue = 15, Data Instance: 0, Key Instance: 0
Hash = 11, KeyValue = 16, Data Instance: 1, Key Instance: 1
Hash = 12, KeyValue = 17, Data Instance: 2, Key Instance: 2
Hash = 13, KeyValue = 18, Data Instance: 3, Key Instance: 3
Hash = 14, KeyValue = 19, Data Instance: 4, Key Instance: 4
_______
Take 2!

Hash = 10, KeyValue = 15, Data Instance: 0, Key Instance: 0
Hash = 11, KeyValue = 16, Data Instance: 1, Key Instance: 1

which is again, exactly as per expectation.

What obviously won’t work here is:

// For this code, accessing it like below, will result in a Segmentation Fault!!!
varArray[1].array->Hash = 11;

Because, in the snippet above I have not initialized varArray[1].array to point to an instance of address of a variable which is of the type BUCKET.
So, if at all by an unintended error/bug you have passed varArray[hash].length * sizeof(BUCKET) to malloc, be certain that you have that much memory allocated if the malloc didn’t return NULL.

And I think that is the exact reason that you are getting a Segmentation Fault when you try to access the next index, by increamenting hash somewhere.

Your statement:

However, the malloc for some reason never creates more than one element in the array. Even when the length is changed.

My guess is, By Segmentation Fault you are assuming that memory is NOT allocated, while it is being allocated. Its just that you are not accessing it the right way.

答案评论:

    
You never set length in your example, even though you warn that it’s important to.
    
@MrLister: Thats the exact point I am willing to convey.
    
But then you should show code that doesn’t work. In this case, your malloc implies length=1, but the OP complains that malloc seems to think length=1 even though he has verified that length=2. That is a completely different situation.
    
@MrLister: Ok, I’ll give it a go then.
    
@MrLister: Can’t do any better than this, at least tonight 🙂

原文地址:

https://stackoverflow.com/questions/47753435/malloc-of-an-array-within-a-struct

Add a Comment