memory allocation in structures - c

My code uses two structures, block and layout (which is a collection of an arbitrary number of blocks).
struct block{
char type;
unsigned short int loc;
unsigned short int size[2];
};
struct layout{
unsigned short int no;
struct block *blocks;
short int **moves;
};
I am using this function to quickly initialize (and partly fill) the structure layout, based a set of blocks:
struct layout init_layout(int block_no, struct block *blocks){
struct layout new_layout;
int i, j;
new_layout.no = (unsigned short int)block_no;
// the following two lines cause an memory corruption error
new_layout.blocks = (struct block *)malloc(block_no);
new_layout.moves = (short int **)malloc(block_no);
for(i = 0; i < block_no; i++){
new_layout.blocks[i] = blocks[i];
new_layout.moves[i] = (short int *)malloc(2);
for(j = 0; j < 2; j++)
new_layout.moves[i][j] = 0;
}
return new_layout;
}
So far, I do not see, that there is something wrong with it. However, when I call function like this
int main(int argc, char** argv){
// just some arbitrary values for 10 blocks
int size[2] = {2, 2};
struct block *blocks = (struct block *)malloc(10);
for(length = 0; length < 10; length++){
blocks[length] = init_block('R', 1, size);
}
struct layout puzzle;
puzzle = init_layout(10, blocks);
return 0;
}
I end up with an memory corruption error, as marked by the comment in init_layout().
What do I miss in my implementation?

When you are allocating memory for anything, you need to analyze, closely -- "What is it that I'm allocating memory for?"
Below, you incorrectly assume a cast of an arbitrary number block_no will adequately size the memory needed for both new_layout.blocks and new_layout.moves -- it won't:
new_layout.blocks = (struct block *)malloc(block_no);
new_layout.moves = (short int **)malloc(block_no);
What you are allocating for new_layout.blocks is actually space for struct block *blocks; (a pointer-to-struct-block), while you can malloc (block_no * sizeof (struct block)); to allocate space for block_no struct block, it is far better to allocate based upon what you are creating (i.e. space for an array new_layout.blocks (again a pointer-to-struct-block) which needs block_no * sizeof *new_layout.blocks bytes of memory to hold block_no of type struct block, e.g.:
new_layout.blocks = malloc(sizeof *new_layout.blocks * block_no);
new_layout.moves = malloc(sizeof *new_layout.moves * block_no);
(simply dereferencing the object you are allocating an array of, will accurate allow you to use sizeof to get the object (element) size for the array. (e.g. sizeof *new_layout.blocks) which you multiply by how many you need (e.g. sizeof *new_layout.blocks * block_no)
The same applies to:
new_layout.moves[i] = malloc(**new_layout.moves * 2);
(note: here you are allocating for 2 shorts, so you will need to dereference you pointer-to-pointer-to-short twice to be allocating for sizeof (short))
See Also: Do I cast the result of malloc? for thorough explanation.

For starters, this
new_layout.blocks = (struct block *)malloc(block_no);
should be
new_layout.blocks = malloc(block_no * sizeof *new_layout.blocks);
For the moves this is a bit more complicated.
Assuming short int **moves; should reference a certain number of int[2] the declaration is not optimal and better should be:
short int (*moves)[2]; /* Define a pointer to
an array with two elements of type short int. */
And allocation then should look like this:
new_layout.moves = malloc(block_no * sizeof *new_layout.moves);
Finally initialisation goes like this:
for(i = 0; i < block_no; i++){
new_layout.blocks[i] = blocks[i];
for(j = 0; j < sizeof new_layout.moves[0]/sizeof new_layout.moves[0][0]; j++)
new_layout.moves[i][j] = 0;
}
You might have noticed:
No memory allocation in the loop any more.
The magic number 2 only appears once.
:-)

Related

Garbage value even after initializing members of dynamically allocated struct array

I have a dynamically allocated array of structures, 'buff'. Each element is a structure that has a few integer variables and a pointer 'buffer_ptr' which points to another dynamically allocated array of structures. The size of both arrays is given as command line input.
int buffer_size;
int user_num;
struct tuple
{
char userID[5];
char topic[16];
int weight;
};
struct buff_ctrl
{
struct tuple* buffer_ptr;
int in;
int out;
int numItems;
int done;
};
The arrays are created and initialized in main() as follows:
int main(int argc, char* argv[])
{
void *status;
pthread_t mapThd;
if(argc != 4)
{
printf("Input format: ./combiner <buffer_size> <number_of_users> <input_file>\n");
return -1;
}
buffer_size = atoi(argv[1]);
user_num = atoi(argv[2]);
struct buff_ctrl *buff = (struct buff_ctrl*)malloc(user_num * sizeof(struct buff_ctrl));
for(int i=0; i<user_num; i++)
{
struct buff_ctrl* curr_buff = (buff + (i*sizeof(struct buff_ctrl)));
struct tuple *ptr = (struct tuple*)malloc(buffer_size * sizeof(struct tuple));
curr_buff->buffer_ptr = ptr;//points to another array
curr_buff->in = 8;
curr_buff->out = 4;
curr_buff->numItems = 7;
curr_buff->done = 0;
printf("%p\n",curr_buff);
}
Then, I need to pass the 'buff' pointer as an argument when creating thread using pthread_create:
pthread_create(&mapThd, NULL, mapper, (void*)buff);
pthread_join(mapThd, &status);
free(buff);
/*end of main*/
My function pointer is as follows:
void* mapper(void *buff)
{
struct buff_ctrl* arr = (struct buff_ctrl *)buff;
struct buff_ctrl* temp_ptr;
printf("######################################################\n");
for(int k=0; k<user_num; k++)
{
/*Printing just to check values */
temp_ptr = arr + (k*sizeof(struct buff_ctrl));
printf("buffer ptr = %p\n", temp_ptr->buffer_ptr);
printf("in = %d\n", temp_ptr->in);
printf("out = %d\n", temp_ptr->out);
printf("numItems = %d\n", temp_ptr->numItems);
}
printf("######################################################\n");
pthread_exit((void*)buff);
}
But, when I print the values of 'buffer_ptr' from the created thread (only one), for ODD number of user_num, there is always ONE element of the array 'buff' which gives garbage value after pthread_create statement! When the values are checked in main itself after removing calls to pthread, it runs fine.
This line
struct buff_ctrl* curr_buff = (buff + (i*sizeof(struct buff_ctrl)));
should be
struct buff_ctrl* curr_buff = buff + i;
buff + i is pointer arithmetic and the compiler already takes the size of the
object pointed to by buff into consideration. By doing i*sizeof(struct buff_ctrl) you are assigning
a pointer that may be after the allocated memory.
As general suggestion:
Don't cast malloc. And instead of using sizeof(<type>), use sizeof *variable, this is more safe, because
it's easier to make mistakes when writing sizeof(<type>).
So:
struct buff_ctrl *buff = malloc(user_num * sizeof *buff);
...
struct tuple *ptr = malloc(buffer_size * sizeof *ptr);
And you don't need to declare a separate pointer, you can do:
for(int i=0; i<user_num; i++)
{
buff[i].buffer_ptr = malloc(buffer_size * sizeof *buff[i].buffer_ptr);
buff[i].in = 8;
buff[i].out = 4;
buff[i].numItems = 7;
buff[i].done = 0;
}
Also you should always check for the return value of malloc. If it returns
NULL, you cannot access that memory.
This is wrong:
struct buff_ctrl* curr_buff = (buff + (i*sizeof(struct buff_ctrl)));
When you do pointer arithmetic, it operates in units of the size of what the pointer points to, so you don't need to multiply by sizeof. As a result, you're effectively multiplying twice and accessing outside the array bounds.
Just treat buff as an array, rather than dealing with pointers.
for(int i=0; i<user_num; i++)
{
struct tuple *ptr = malloc(buffer_size * sizeof(struct tuple));
buff[i].buffer_ptr = ptr;//points to another array
buff[i].in = 8;
buff[i].out = 4;
buff[i].numItems = 7;
buff[i].done = 0;
}
Also, see Do I cast the result of malloc?
You have a fundamental error.
Pointer arithmetics works by adding the offset in multiples of the pointer type, so adding the offset yourself will not work as you apparently expect it to.
If it was a char * pointer then you would need to add the offset manually, increments would be multiplied by one. But in your case increments by n are multiplied by the size of the pointer base type.
There are times when doing pointer arithmetics with the addition notation makes sense, but most of the time it's much clearer to write index notation instead.

project struct to a array of bytes in c

Suppose I have array of chars:
char buffer[1024];
The array in fact contains chain of structures in sequence.
struct MyStruct {
char name[4];
int num1;
int num2;
}
I want to loop through the array:
MyStruct *p;
for(int i = 0;i < sizeof(buffer);i += sizeof(MyStruct))
{
// how can I point p to some place in buffer here?
}
I want to point p to start of buffer, the to buffer + 12 etc.
One issue to consider is that the char buffer might not be properly aligned for a struct (and, in this case, its int members num1 and num2). Depending on the platform and implementation, a 4-byte, 8-byte or 16-byte alignment might be required. For that reason, one alternative is to declare the buffer in terms of MyStruct initially and then access it via a char pointer:
MyStruct buffer[1024 / sizeof(MyStruct)];
char * cp = (char *) buffer;
// fill the buffer via cp
for (size_t i = 0; i < sizeof(buffer); ++i)
{
// do stuff with buffer[i]
}
If that approach is not possible, the buffer needs to be copied to another buffer with safe alignment; For example:
size_t n = sizeof(buffer) / sizeof(MyStruct);
MyStruct * p = (MyStruct *) malloc(n * sizeof(MyStruct));
if (!p) { exit(EXIT_FAILURE); }
memcpy(p, buffer, n * sizeof(MyStruct)); // copy buffer to p
for (size_t i = 0; i < n; ++i)
{
// do stuff with p[i]
}
first note that you are assuming that this will work. That there is no padding between the elements of the struct. Having said that do this:
MyStruct *s = (MyStruct*)(buffer + i)
You let p point to the first struct in the buffer, then increment it on each iteration:
MyStruct *p= (struct MyStruct *) buffer;
for(int i = 0; i < sizeof(buffer); i += sizeof(MyStruct), p++)
{
// your code
}
...and yes, this assumes the structs are contiguous in memory, with no padding in between.

Setting pointer in struct to an array in C

I am debugging some code and just wanted to make sure that the way I am setting a pointer to an array inside my struct is correct.
Here is an example of what I am trying to do:
typedef struct Foo
{
uint32_t *bar;
} Foo
int main(void)
{
Foo *foo;
uint32_t *bar[20];
foo = (Foo *)malloc(sizeof(Foo));
*bar = malloc(sizeof(uint32_t) * 20);
for(int i = 0; i < 20; i++)
{
bar[i] = (uint32_t*)malloc(sizeof(uint32_t));
}
foo->bar = *bar;
}
The code
uint32_t *bar[20];
declares bar as an array of 20 pointers to uint32_t which is probably not what you intended. Since you allocate the array dynamically with malloc, you should declare bar as a pointer rather than an array:
uint32_t **bar;
You may want to consider doing the memory allocation in a single malloc() rather than the piecewise approach you are using. For instance you might want to consider doing something like the following.
This allocates the memory needed in a single call to malloc() so that only a single call to free() is needed to release the memory. It is faster and tends to make the heap to be less fragmented and easier to manage.
typedef struct
{
uint32_t *bar[1]; // an array of size one that makes array syntax easy
} Foo;
Foo *FooCreateFoo (unsigned int nCount)
{
// create an array of pointers to uint32_t values along with the
// memory area for those uint32_t data values.
Foo *p = malloc (sizeof(uint32_t *) * nCount + sizeof(uint32_t) * nCount);
if (p) {
// we have memory allocated so now initialize the array of pointers
unsigned int iLoop;
uint32_t *pData = p->bar + nCount; // point to past the last array element
for (iLoop = 0; iLoop < nCount; iLoop++) {
// set the pointer value and initialize the data to zero.
*(p->bar[iLoop] = pData++) = 0;
}
}
return p;
}
int main(void)
{
Foo *foo = FooCreateFoo (20);
if (! foo) {
// memory allocation failed so exit out.
return 1;
}
// ... do things with foo by dereferencing the pointers in the array as in
*(foo->bar[1]) += 3; // increment the uint32_t pointed to by a value of 3
free (foo); // we be done with foo so release the memory
}

2 dimensional array in struct

I have to implement game of life, it is almost complete, the last thing I want to do is to allocate my field dynamical. I'm working under Windows, got no Valgrind and I don't no what's the error in my code. Eclipse shows only that the process is not functional anymore.
Can anyone tell me, what's the problem in my code? Or maybe I don't need a 2 dim. array for game of life field?
struct game_field {
int length;
int **field;
};
static struct game_field *new_game_field(unsigned int l) {
struct game_field *pstField;
pstField = calloc(1, sizeof(struct game_field));
pstField->length = l;
pstField->field = malloc(l * sizeof(int*));
for( int i = 0; i < l; i++ ) {
pstField->field[i] = malloc(l * sizeof(int));
if(NULL == pstField->field[i]) {
printf("No memory for line %d\n",i);
}
}
return pstField;
}
You should think a little bit about the structures and what you are storing.
For the game of life you need to know the state of the cell on the board which is indicated by and integer so your struct should become:
struct game_field {
int length;
int *field;
};
And once you know the dimensions of the field you should allocate it once:
struct game_field *gf = calloc(1, sizeof(struct game_field));
gf->length = <blah>;
gf->field = malloc(gf->length*gf->length*sizeof(int));
This way you have an array of integers that you can use as your board.
The first malloc should be:
pstField->field = malloc(l * sizeof(int*));
Your array is int**, so the first level of allocation is an int*.
Edit: Well, I've tested your code and it does not crash for me. The problem might be somewhere else.
Here's a modification of your code that allocates the field in one block, but still lets you use array brackets for both dimensions:
struct game_field {
int length;
int **field;
};
static struct game_field *new_game_field(unsigned int len)
{
struct game_field *pstField;
pstField = malloc(sizeof(struct game_field));
pstField->length = len;
/* allocate enough space for all the row pointers + the row contents */
pstField->field = malloc((len * sizeof(int *)) + (len * len * sizeof(int)));
/* point the row pointers (at the start of the block) at the row contents
* (further into the block). */
for (int i = 0; i < len; i++)
pstField->field[i] = (int *)(&field[len]) + (i * len);
return pstField;
}
This way you can free the field in one shot:
void free_game_field(struct game_field *gf)
{
free(gf->field);
free(gf);
}
And you can keep the bracket notation to access the elements:
int row7col3 = gf->field[7][3];
Note that what you have (here as well as in your original code) is not exactly a two-dimensional array, but an array of pointers to arrays of integers
(there is a difference, but the arr[x][y] notation can work for either one).

how to initialize the array of pointers to a structure to zero

I am allocating memory for array of pointers to structure through malloc and want to initialize it with zero like mentioned below . Assuming the structure contains member of type int and char [] (strings) ? so how can i zero out this struct.
Code : suppose i want to allocate for 100
struct A **a = NULL;
a = (struct **)malloc(sizeof( (*a) * 100);
for(i=1; i < 100; i++)
a[i] = (struct A*)malloc(sizeof(a));
Also please explain me why is it necessary to initialize with zero .
Platform : Linux , Programing language : C
I know we can use memset or bzero . I tried it bt it was crashing , may be i was noy using it properly so pls tell me the correct way .
Use of calloc would be most in line with the example above.
First, C arrays are zero-based, not one-based. Next, you are allocating only enough space to hold one pointer, but you are storing 100 pointers into it. Are you trying to allocate 100 As, or are you trying to allocate 100 sets of 100 As each? Finally, the malloc inside your loop allocates space for the sizeof a, not sizeof (struct A).
I'll assume that you are trying to allocate an array of 100 pointers to A, each pointer pointing to a single A.
Solutions: You could use calloc:
struct A **a;
/* In C, never cast malloc(). In C++, always cast malloc() */
a = malloc(100 * sizeof( (*a)));
for(i=0; i < 100; i++)
a[i] = calloc(1, sizeof(struct A));
Or, you could use memset:
struct A **a;
a = malloc(100 * sizeof(*a));
for(i = 0; i < 100; i++) {
a[i] = malloc(sizeof(struct A));
memset(a[i], 0, sizeof(struct A));
}
You ask "why is it necessary to initialize with zero?" It isn't. The relevant requirement is this: you must assign a value to your variables or initialize your variable before you use them for the first time. That assignment or initialization might be zero, or it might be 47 or it might be "John Smith, Esq". It just has to be some valid assignment.
As a matter of convenience, you might choose to initialize all of your members of struct A to zero, which you can do in one single operation (memset or calloc). If zero is not a useful initial value for you, you could initialize the structure members by hand, for example:
struct A **a;
a = malloc(100 * sizeof(*a));
for(i = 0; i < 100; i++) {
a[i] = malloc(sizeof(struct A));
a[i]->index = i;
a[i]->small_prime = 7;
strcpy(a[i]->name, name_database[i]);
}
As long as you never refer to the value of an uninitialized and unassigned variable, you are good.
You can use memset() to set the whole array to 0
OTOH,
a = (struct **)malloc(sizeof( (a*)));
for(i=1; i < 100; i++)
a[i] = (struct*)malloc(sizeof(a) * 100);
is wrong, because you have just created one element of a * but in the next line when the loop goes to 2nd iteration, it will access illegal memory. So to allocate 100 elements of a *, your first malloc() should be as follows
a = (struct **)malloc(sizeof(a *) * 100);
The correct code (including error handling) would more or less will look as follows:
if ((a = (struct **)malloc(sizeof(a*) * 100)) == NULL) {
printf("unable to allocate memory \n");
return -1;
}
for(i=0; i<100; i++) {
if ((a[i] = (struct*)malloc(sizeof(a) * 100)) == NULL) {
printf("unable to allocate memory \n");
return -1;
}
memset(a[i], 0, 100);
}
or as an alternative to malloc() and memset(), you can use calloc()
You dont need many malloc's, one calloc is enough:
int i;
struct A **a = calloc(100,sizeof**a+sizeof*a),*mem=a+100;
for(i=0;i<100;++i)
{
a[i]=&mem[i];
}
...
free(a); /* and you only need ONE free */

Resources