Allocating works the same for all types. If you need to allocate an array of line structs, you do that with:
struct line* array = malloc(number_of_elements * sizeof(struct line));
In your code, you were allocating an array that had the appropriate size for line pointers, not for line structs. Also note that there is no reason to cast the return value of malloc().
Note that's it's better style to use:
sizeof(*array)
instead of:
sizeof(struct line)
The reason for this is that the allocation will still work as intended in case you change the type of array. In this case this is unlikely, but it's just a general thing worth getting used to.
Also note that it's possible to avoid having to repeat the word struct over and over again, by typedefing the struct:
typedef struct line
{
char* addr;
char* inst;
} line;
You can then just do:
line* array = malloc(number_of_elements * sizeof(*array));
Of course don't forget to also allocate memory for array.addr and array.inst.
Allocating works the same for all types. If you need to allocate an array of line structs, you do that with:
struct line* array = malloc(number_of_elements * sizeof(struct line));
In your code, you were allocating an array that had the appropriate size for line pointers, not for line structs. Also note that there is no reason to cast the return value of malloc().
Note that's it's better style to use:
sizeof(*array)
instead of:
sizeof(struct line)
The reason for this is that the allocation will still work as intended in case you change the type of array. In this case this is unlikely, but it's just a general thing worth getting used to.
Also note that it's possible to avoid having to repeat the word struct over and over again, by typedefing the struct:
typedef struct line
{
char* addr;
char* inst;
} line;
You can then just do:
line* array = malloc(number_of_elements * sizeof(*array));
Of course don't forget to also allocate memory for array.addr and array.inst.
For what you have described, You do not need to allocate memory for your struct, rather, you need to allocate memory for the members char *addr;, and char *inst;. If you want to have a single copy of that structure, the first section of code illustrates how to initialize, and assign values. If you want an array, the second code example illustrates the differences.
This illustrates how to allocate memory for the members of a single struct line:
typedef struct
{
char* addr;
char* inst;
}LINE;
LINE line;
int main(void)
{
strcpy(line.addr, "anystring"); //will fail
line.addr = malloc(80);
line.inst = malloc(80);
strcpy(line.addr, "someString");//success;
strcpy(line.inst, "someOtherString");//success;
}
For array of struct line...
typedef struct
{
char* addr;
char* inst;
}LINE; //same struct definition
LINE line[10]; //but create an array of line here.
int main(void)
{
int i;
for(i=0;i<10;i++)
{
line[i].addr = malloc(80);
line[i].inst = malloc(80);
}
for(i=0;i<10;i++)
{
strcpy(line[i].addr, "someString");
strcpy(line[i].inst, "someOtherString");
}
//when done, free memory
for(i=0;i<10;i++)
{
free(line[i].addr);
free(line[i].inst);
}
}
Added to address comment
Addressing the comment under this answer from @Adam Liss, the following code illustrates the following improvements using strdup(): 1) Uses only memory needed. 2) Performs memory creation and copy operations in one step, so the the following blocks:
for(i=0;i<10;i++)
{
line[i].addr = malloc(80);
line[i].inst = malloc(80);
}
for(i=0;i<10;i++)
{
strcpy(line[i].addr, "someString");
strcpy(line[i].inst, "someOtherString");
}
Become:
for(i=0;i<10;i++)
{
line[i].addr = strdup("someString");
line[i].inst = strdup("someOtherString");
}
One more note: Error handling was not included in examples above to avoid muddling up focus on the main concepts: But for the sake of completeness, because both malloc() and strdup() can fail, actual usage for each of these two functions, should include a test before using, eg:
Rather than
line[i].addr = strdup("someString");
line[i].inst = strdup("someOtherString");
The code should include
line[i].addr = strdup("someString");
if(!line[i].addr)
{
//error handling code here
}
line[i].inst = strdup("someOtherString");
if(!line[i].inst)
{
//error handling code here
}
struct key* PrevKeys= malloc(345000*sizeof(struct key));
struct key* ActivityKeys= malloc(345000*sizeof(struct key));
struct key* CurKeys= malloc(345000*sizeof(struct key));
You're trying to assign the result of malloc, which is a pointer, to a struct, which is not possible. You have to declare them as pointers:
struct key *PrevKeys = malloc(345000 * sizeof(struct key));
...
and don't forget to free the memory:
free(PrevKeys);
If you're still getting errors, try to allocate just 10 elements, and if it works, you can be sure 345000 elements is too much.
Also, I'd prefer to not use sizeof(struct key) but sizeof(*PrevKeys) since it will always return the right size for PrevKeys, even if you change the type of PrevKeys.
How to malloc arrays inside structs?
c - malloc an array of struct pointers - Stack Overflow
c - How to free() an array of structs allocated by malloc()? - Stack Overflow
c - Malloc an array of structs. - Stack Overflow
Videos
I would like to have a struct containing several dynamically allocated arrays. I've tried several variations of the following code:
#include<stdio.h>
#include<stdlib.h>
struct rectangle
{
int
width,
height;
int*
arr1,
arr2;
};
int main()
{
int n = 3;
struct rectangle box1 =
{
.width = 3,
.height = 4,
.arr1 = (int*) malloc( n * sizeof(int)),
.arr2 = (int*) malloc( n * sizeof(int))
};
}
However, I keep getting warning: initialization from int to int* makes integer from pointer without a cast [-Wint-conversion].
array is a slightly misleading name. For a dynamically allocated array of pointers, malloc will return a pointer to a block of memory. You need to use Chess* and not Chess[] to hold the pointer to your array.
Chess *array = malloc(size * sizeof(Chess));
array[i] = NULL;
and perhaps later:
/* create new struct chess */
array[i] = malloc(sizeof(struct chess));
/* set up its members */
array[i]->size = 0;
/* etc. */
There's a lot of typedef going on here. Personally I'm against "hiding the asterisk", i.e. typedef:ing pointer types into something that doesn't look like a pointer. In C, pointers are quite important and really affect the code, there's a lot of difference between foo and foo *.
Many of the answers are also confused about this, I think.
Your allocation of an array of Chess values, which are pointers to values of type chess (again, a very confusing nomenclature that I really can't recommend) should be like this:
Chess *array = malloc(n * sizeof *array);
Then, you need to initialize the actual instances, by looping:
for(i = 0; i < n; ++i)
array[i] = NULL;
This assumes you don't want to allocate any memory for the instances, you just want an array of pointers with all pointers initially pointing at nothing.
If you wanted to allocate space, the simplest form would be:
for(i = 0; i < n; ++i)
array[i] = malloc(sizeof *array[i]);
See how the sizeof usage is 100% consistent, and never starts to mention explicit types. Use the type information inherent in your variables, and let the compiler worry about which type is which. Don't repeat yourself.
Of course, the above does a needlessly large amount of calls to malloc(); depending on usage patterns it might be possible to do all of the above with just one call to malloc(), after computing the total size needed. Then you'd still need to go through and initialize the array[i] pointers to point into the large block, of course.
How should i free the allocated memory that was used after calling malloc?
Consider below example,
struct datastore1 *obj1 = malloc(sizeof(struct datastore1));
free(obj1);
Here obj1 is pointing to the block of memory of size same as size of datastore1 in order to free you need to send the address which is allocated by malloc.

likewise,
struct datastore1 *obj2 = malloc(3 * sizeof(struct datastore1));
free(obj2);
obj2 is pointing to a block of contiguous memory of size 3 * sizeof(datastore1) you need to pass the base address to free

Should i free each indexes individually?
NO, Since block of memory is allocated only once and you need to free exactly one time.
Let me extend it further,
struct datastore1 *obj3[3];
for(int i=0;i<3;i++)
obj3[i] = malloc(sizeof(struct datastore1));
for(int i=0;i<3;i++)
free(obj3[i]);
Here obj3 is array of pointer and each index is pointing to different part of memory and hence need to be freed individually.

Note: For simplicity I haven't considered return value from malloc. Null check has to be done on malloc return value.
1.
How should I free the allocated memory that was used after calling malloc?
I tried doing
free(dsdata)on the end of the program but I am not sure if it's the right way.
free(dsdata) is fine, since you allocated the whole space by just one call to malloc with:
struct datastore1 *dsdata = malloc(30 * sizeof(struct datastore1));
To cite the standard (C18), 7.22.3.4 - "The malloc function" (emphasize mine):
7.22.3.4 The malloc function
Synopsis
1
#include <stdlib.h> void* malloc(size_t size);Description
2 The malloc function allocates space for an object whose size is specified by size and whose value is indeterminate.
Returns
3 The malloc function returns either a null pointer or a pointer to the allocated space.
It is correct to use free(dsdata) because malloc allocated all of the required space at once and returned a pointer to the first structure variable of this array which is assigned to the pointer of dsdata.
The free() function "knows" that dsdata is a reference to the whole allocated space. You do not need to free each of the 30 structures of type struct datastore1 in memory individually.
2.
Should I free each indexes individually?
No, you do not need and even more important you should not do so; this would be Undefined Behavior:
Citation from the current standard (C18), 7.22.3.5/3 - "The free function" (emphasize mine):
Otherwise, if the argument does not match a pointer earlier returned by a memory management function, or if the space has been deallocated by a call to free or realloc, the behavior is undefined.
Your problem is the way you declared the struct it should be
Copystruct data
{
int *ref;
int *port;
char data[MAX_STRING];
};
and then you do
Copystruct data *p_valid;
p_valid = malloc(sizeof(struct data));
another thing is
Copyp_valid->data = malloc(sizeof(STRINGMAX));
is wrong because data is not a pointer. And sizeof(STRINGMAX) is wrong too, since STRINGMAX seems to be a macro and hence it will expand to it's value say if you have #define STRINGMAX 4 then it would expand to sizeof(4).
CopyYour definition of the struct:
struct data {
int *ref;
int *port;
char data[MAX_STRING];
}temp, valid, invalid;
should be more like this:
struct data
{
int *ref;
int *port;
char data[MAX_STRING];
};
then define the arrays similar to this:
struct data temp;
struct data* valid = NULL;
struct data* invalid = NULL;
int currentValidSize = 0;
int currentInvalidSize = 0;
struct data * validTemp = NULL;
struct data * invalidTemp = NULL;
then, each time the code needs room for (another) instance of a struct
struct data *validTemp = realloc(valid, (currentValidSize+1)* sizeof(data) );
if( NULL == validTemp )
{ // realloc failed
perrof( "realloc failed" );
// free everything, close files, etc here probably be writing a sub function
// and calling it here.
// a sub function that:
// that walks the valid and invalid arrays,
// first free'ing any malloc'd fields
// then finally free'ing the whole array
exit( EXIT_FAILURE );
}
// implied else, realloc successful
// update array size counter
currentValidSize++;
// update ptr to valid array of structs
valid = validTemp;
validTemp = NULL;
similar for adding an entry to the invalid array of structs
then update the valid array of structs from temp as:
(note the '-1' in the offset into valid[])
memcpy( &valid[currentValidSize-1], &temp, sizeof data );
// Note you will also have to perform a 'deep' copy of any areas
// that were malloc'd within the 'temp' struct
I am also concerned if there can be situation that I free a pointer twice in my case
... and ...
Yes just I am more interested in cases when/if there can be for example freeing unallocated memory or freeing already freed memory ...
After a quick inspection it doesn't appear that you free memory more than once:
freestatements are only in thefreeArrayandmainmethods- Each
free(a->array[0].name);is different because each name is allocated using its own malloc free(a->array)is only called oncefreeArrayis only called oncefree(x.name);doesn't free the same memory asfree(a->array[0].name);becauseinsertArrayallocates new memory for each name
and how to avoid that
Something which can help (though not guarantee) is to assign NULL to the pointer after you pass it to free.
- It can help, because calling free on a previously-nulled pointer will harmlessly do nothing
- It's not a guarantee, because you might have more than one pointer pointing to the same memory
dmcr_code's comment below points out a bug. You wrote,
for(int i=0; i<a->used; i++)
{
free(a->array[0].name);
a->array[0].name=NULL;
}
This should be,
for(int i=0; i<a->used; i++)
{
free(a->array[i].name);
a->array[i].name=NULL;
}
Because you set a->array[0].name=NULL; after freeing it, you don't free it twice.
But, you did fail to free the memory associated with a->array[i].name for values of i larger than 0.
But then how do I protect against that - when array[i].name can contain random value and I try to free it?
To protect yourself:
- Either, don't let it contain a random value (e.g. ensure that it's either a valid pointer, or zero)
- Or, don't use it (e.g. ensure that your
a->usedlogic is correct so that you don't touch elements which you haven't used/initialized).
is memset in the initArray method fine for that?
memset is good:
- You could use calloc instead of malloc to avoid having to use memset as well
- You could use memset on the whole array at once instead of using memset on each element of the array
memset in initArray isn't enough. It's enough to begin with, but there's a realloc in insertArray. So to be good enough, you'd also need to use memset after realloc (to memset the as-yet-unused end of the newly-reallocated array; without using memset on the beginning of the reallocated array, which already contains valid/initialized/used elements).
the only unclear part that remains from your response is how to memset realloced array
Your current code in initArray says,
// Initialize all values of the array to 0
for(unsigned int i = 0; i<initialSize; i++)
{
memset(&a->array[i],0,sizeof(Student));
}
Another way to do that would be:
// Initialize all elements of the array at once: they are contiguous
memset(&a->array[0], 0, sizeof(Student) * initialSize);
The memset statement to add to insertArray would be:
if (a->used == a->size)
{
a->size *= 2;
a->array = (Student *)realloc(a->array, a->size * sizeof(Student));
// Initialize the last/new elements of the reallocated array
for(unsigned int i = a->used; i<a->size; i++)
{
memset(&a->array[i],0,sizeof(Student));
}
}
Or:
if (a->used == a->size)
{
a->size *= 2;
a->array = (Student *)realloc(a->array, a->size * sizeof(Student));
// Initialize the last/new elements of the reallocated array
memset(&a->array[a->used],0,sizeof(Student) * (a->size - a->used));
}
and this comment: "It's not a guarantee, because you might have more than one pointer pointing to the same memory " would be nice if you can address that too
This is safe:
void* foo = malloc(10);
free(foo);
// protect against freeing twice
foo = NULL;
// this is useless and strange, but harmless
free(foo);
This is not safe:
void* foo = malloc(10);
void* bar = foo;
free(foo);
// protect against freeing twice
foo = NULL;
// this is useless and strange, but harmless
free(foo);
// but this is dangerous, illegal, undefined, etc.
// because bar is now pointing to memory that has already been freed
free(bar);
I have 3 suggestions.
If you need to allocate memory and initialize it to zero use
calloc.
Usingcallocis better than usingmalloc + memsetSo change your
initArrayfunction like:void initArray(Array *a, size_t initialSize) { // Allocate initial space a->array = (Student *)calloc(initialSize , sizeof(Student)); a->used = 0; // no elements used a->size = initialSize; // available nr of elements }Single character variable names are very bad. Use proper names for variables and follow naming conventions.
In your code you are only creating and adding 3 objects. But you are trying to print the details of 4th object. (Array index is starting from zero, so index 3 means 4th object)
printf("%d\n", a.array[3].ID); printf("%s\n", a.array[3].name);
If I had your code and had to improve it, I'd go for
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
// The kernel style guide https://www.kernel.org/doc/html/v4.10/process/coding-style.html discourages typedefs for structs
typedef struct moeda {
double *return_value;
} moeda;
// return a struct here:
moeda initialize_return(int a)
{
moeda ret;
ret.return_value = malloc(a*sizeof(double));
return ret;
}
int main(void) {
long int a=250;
moeda m = initialize_return(a);
m.return_value[0] = 2000;
printf("%lf", m.return_value[0]);
return 0;
}
(it is better to have all identifiers in English).
This would be the first step to do. Then I might realize that the struct isn't really needed and replace it:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
double * initialize_double_array(int a)
{
return malloc(a*sizeof(double));
}
int main(void) {
long int a=250;
double * arr = initialize_double_array(a);
arr[0] = 2000;
printf("%lf", arr[0]);
return 0;
}
OTOH, if there are other fields in the said struct, I might decide if they are supposed to be initialized along with this array or not.
Some variants:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
// The kernel style guide https://www.kernel.org/doc/html/v4.10/process/coding-style.html discourages typedefs for structs
struct moeda {
int num_values;
double *values;
};
// only fill a struct here:
// i. e. take a pre-initialized struct and work with it:
void moeda_alloc_values(struct moeda * data)
{
data->return_value = malloc(data->num_values * sizeof(double));
}
// return a struct here:
struct moeda initialize_moeda(int num)
{
struct moeda ret;
ret.num_values = num;
ret.return_value = malloc(num * sizeof(double));
// or just moeda_alloc_values(&ret);
return ret;
}
int main(void) {
long int a=250;
struct moeda m = initialize_return(a);
m.return_value[0] = 2000;
printf("%lf", m.return_value[0]);
struct moeda m2;
m2.num_values = 20;
moeda_alloc_values(&m2);
m2.return_value[0] = 2000;
printf("%lf", m2.return_value[0]);
return 0;
}
The struct returning function has the advantage that you have a "readily filled" structure after return.
The other function which modifies a struct via a pointer on it has the advantage that it can work on any, possibly pre-filled, possibly malloced struct and that it can work on single fields instead having to consider all fields.
First of all return is a reserved keyword in C and you can not use a reserved keyword as a variable name.
Second,If you want to allocate memory for array of any data type in other function then,declare a variable in the function,call malloc,allocate required space through malloc and return the address of the first element of allocated space.If you do not return the address the allocated space would not be known to the called function(here main()) and it could not be able to access the allocated memory space.You can do like this:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
typedef struct
{
double *var;
}moeda;
double *ini(int n)
{
double *arr;
arr = malloc(n*sizeof(*arr));
return arr;
}
int main(void){
long int a=250;
moeda m;
m.var=ini(a);
m.var[0] = 2000;
printf("%lf", m.var[0]);
return 0;
}