Dynamic memory allocation for structs in c - c

I am trying to initialise a struct by allocating memory to it and it's pointer members using malloc:
typedef struct {
char *name;
prob_t *prob;
} name_t;
I understand that I need to allocate memory to the pointers separately once the struct is initialised:
name_t
*init_name_dict() {
name_t *name_dict;
name_dict = (name_t*)malloc(MAX_LINES*sizeof(*name_dict));
name_dict->name = (char*)malloc(MAX_LEN*sizeof(*name_dict->name));
name_dict->prob = (prob_t*)malloc(MAX_PROB*sizeof(*name_dict->prob));
return name_dict;
}
But when I do so, it allocates memory to the struct, but not to either of its member pointers (they just point to junk).
What am I doing wrong? Thanks

As explained here, malloc doesn't "clean" the memory, that then can be full of garbage (because for example the same memory was returned by another call to malloc(), used and then free()). The three classical solutions are:
Live with it. Set manually all the members of the struct (if you are
using the malloc to allocate a struct) before using the struct (or in general set the all the obtained memory to the value you want)
Use memset to zero all the memory before using it
Use calloc instead of malloc (note that it has a slightly different signature). calloc is similar to malloc + memset. As an example:
name_t *init_name_dict() {
name_t *name_dict;
name_dict = calloc(MAX_LINES, sizeof(*name_dict));
name_dict->name = calloc(MAX_LEN, sizeof(*name_dict->name));
name_dict->prob = calloc(MAX_PROB, sizeof(*name_dict->prob));
return name_dict;
}
As a sidenote, in C you don't need/shouldn't cast a pointer returned by malloc/calloc (but if in truth you are using a C++ compiler then you have to cast it...).

If you want cleared memory (as opposed to memory with junk in it), you need calloc
instead of malloc, but that's trivial.
You're bigger problems are:
1) no error checking
2) possibly needless malloc calls
3) you're allocating MAX_LINES of theses name_t structure but initializing
only one of them
If the .name and .prob fields won't be reallocated, you should change your name_t
definition to
typedef struct { char name[MAX_LEN]; prob_t prob[MAX_PROB]; } name_t;
and allocate all MAX_LINES name_t's in one go: calloc(MAX_LINES, sizeof(name_t)).
If you need the original name_t structure, then I'd have an initializer for one:
int init_name_dict (name_t *this)
{
if(0==(this->name=calloc(MAX_LEN, sizeof *this->name))) return -1;
if(0==(this->prob=calloc(MAX_PROB, sizeof *this->prob))){ free(this->name); return -1; }
return 0;
}
a destructor for it
void destroy_name_dict(name_t *this) { free(this->name); free(this->prob); }
and then an initializing allocator for the whole array:
name_t* new_name_dicts(void)
{
name_t *r = malloc(MAX_LINES*sizeof *r);
if(!r) return r;
int i;
for(i=0; i<MAX_LINES; i++)
if(0>init_name_dict(&r[i])) goto fail;
return r;
fail:
for(--i; i>=0; --i)
destructor_name_dict(&r[i]);
return NULL;
}
(Basically what would amount to a C++ vector constructor that picks up the constructor for the
cell type.)

Struct
typedef struct {
char *name;
prob_t *prob;
} name_t;
has two pointers as members. So on 32 bit OS, sizeof(name_t) is 8 bytes.
Dynamic creation of instance of name_t struct
name_t *name_dict = (name_t*)malloc(sizeof(name_dict));
allocates only 8 bytes to store two pointers. As xanatos said allocated memory is garbage and pointers will point random locations. You can use calloc() when allocation name_dict or manually nullify them name_dict->name = NULL;name_dict->prob = NULL;. You can also don't bother yourself by content of pointers and in next code line allocate memory to members
name_dict->name = (char*)malloc(MAX_LEN*sizeof(char));
name_dict->prob = (prob_t*)malloc(sizeof(prob_t));
You can also check if memory was allocated good and both pointers don't ppoint to NULL.
To sum up, properly written init_name_dict() method
name_t * init_name_dict()
{
name_t *name_dict = (name_t*)malloc(sizeof(name_t));
if (name_dict != NULL)
{
name_dict->name = (char*)malloc(MAX_LEN*sizeof(char)));
name_dict->prob = (prob_t*)malloc(sizeof(prob_t));
}
return name_dict;
}
Errors in your code was
MAX_LINES here(assume that you want to create only one structure here)
name_dict = (name_t*)malloc(MAX_LINES*sizeof(*name_dict));
MAX_PROB here (assume that you want to create only one structure
here)
name_dict->prob = (prob_t*)malloc(MAX_PROB*sizeof(*name_dict->prob));

Related

Initialize an empty nested struct using a function

I have to initialize tCoworking coworking by implementing init_coworking function that is declared at the end.
/* Constants *********************************************************/
#define nWorkSpaces 50
#define unlimited 2000
/* Types *************************************************************/
typedef enum {tableFlex, tableFix, officeFix} rate;
typedef char string[55];
typedef struct {
int reservationId;
float monthPayment;
} tContractAnnex;
typedef struct {
int id;
string name;
int discount;
} tPartner;
typedef struct {
int id;
float surface;
rate rateType;
} tWorkspace;
typedef struct {
int partnerId;
int month;
int year;
tContractAnnex annex;
} tContract;
typedef struct {
tWorkspace workSpace[nWorkSpaces];
tContract contract[unlimited];
tPartner partner[unlimited];
} tCoworking;
/* Function declaration */
void init_coworking(tCoworking *coworking);
As you can see the problem I have is that tCoworking is a nested struct with array of stucts as data types..
So far I'm doing this in order to initialize it but it must be a better way to do it.
void init_coworking(tCoworking *coworking){
coworking = malloc(sizeof(tCoworking));
coworking->partner[0].id = 0;
coworking->partner[0].discount = 0;
strcpy(coworking->partner[0].name, "");
coworking->workSpace[0].id = 0;
coworking->workSpace[0].rateType = 0;
coworking->workSpace[0].surface = 0;
coworking->contract[0].partnerId = 0;
coworking->contract[0].year = 0;
coworking->contract[0].month = 0;
coworking->contract[0].annex.monthPayment = 0;
coworking->contract[0].annex.reservationId = 0;
}
void init_coworking(tCoworking *coworking) {
coworking && memset( coworking, 0, sizeof( tCoworking ) );
}
memset initializes a block of memory - of specifiable length - to a single byte value. Your example indicates that you desire zero-initialization of the entire object, so memset serves this purpose well.
NULL-check your input argument.
I recommend you not malloc or calloc in your function because your function signature implies that the caller is the owner of the tCoworking. If you malloc within your init_coworking() function, then you'll have created a new heap-allocated instance of a tCoworking with no clear ownership. You can try keep track of newly-allocated objects in some type of container, but that's going far beyond the scope of your question -- keep it simple.
The simplest way is to use calloc. Like malloc it allocates memory for you but it also sets all the memory to zero.
However - more important is that your current function doesn't make sense. The memory you allocate is simply lost. The caller of init_coworking will never get the allocated and initialized memory.
Either you should:
Not do any malloc(or calloc)
or
Return the malloced pointer.
Since the prototype suggest that you get a tCoworking pointer, the most likely thing is that it's already allocated (in some way), i.e. you want option 1.
So just do:
void init_coworking(tCoworking *coworking){ // NO malloc
memset(coworking, 0, sizeof(tCoworking));
}
In case you only want the first array member set to zero (like your code indicates) you may get a little performance improvement by:
void init_coworking(tCoworking *coworking){ // NO malloc
memset(&coworking->partner[0], 0, sizeof(coworking->partner[0]));
... similar for the other arrays ...
}
but I doubt that's worth the trouble...

How to allocate memory dynamically for a struct [duplicate]

I have looked around but have been unable to find a solution to what must be a well asked question.
Here is the code I have:
#include <stdlib.h>
struct my_struct {
int n;
char s[]
};
int main()
{
struct my_struct ms;
ms.s = malloc(sizeof(char*)*50);
}
and here is the error gcc gives me:
error: invalid use of flexible array member
I can get it to compile if i declare the declaration of s inside the struct to be
char* s
and this is probably a superior implementation (pointer arithmetic is faster than arrays, yes?)
but I thought in c a declaration of
char s[]
is the same as
char* s
The way you have it written now , used to be called the "struct hack", until C99 blessed it as a "flexible array member". The reason you're getting an error (probably anyway) is that it needs to be followed by a semicolon:
#include <stdlib.h>
struct my_struct {
int n;
char s[];
};
When you allocate space for this, you want to allocate the size of the struct plus the amount of space you want for the array:
struct my_struct *s = malloc(sizeof(struct my_struct) + 50);
In this case, the flexible array member is an array of char, and sizeof(char)==1, so you don't need to multiply by its size, but just like any other malloc you'd need to if it was an array of some other type:
struct dyn_array {
int size;
int data[];
};
struct dyn_array* my_array = malloc(sizeof(struct dyn_array) + 100 * sizeof(int));
Edit: This gives a different result from changing the member to a pointer. In that case, you (normally) need two separate allocations, one for the struct itself, and one for the "extra" data to be pointed to by the pointer. Using a flexible array member you can allocate all the data in a single block.
You need to decide what it is you are trying to do first.
If you want to have a struct with a pointer to an [independent] array inside, you have to declare it as
struct my_struct {
int n;
char *s;
};
In this case you can create the actual struct object in any way you please (like an automatic variable, for example)
struct my_struct ms;
and then allocate the memory for the array independently
ms.s = malloc(50 * sizeof *ms.s);
In fact, there's no general need to allocate the array memory dynamically
struct my_struct ms;
char s[50];
ms.s = s;
It all depends on what kind of lifetime you need from these objects. If your struct is automatic, then in most cases the array would also be automatic. If the struct object owns the array memory, there's simply no point in doing otherwise. If the struct itself is dynamic, then the array should also normally be dynamic.
Note that in this case you have two independent memory blocks: the struct and the array.
A completely different approach would be to use the "struct hack" idiom. In this case the array becomes an integral part of the struct. Both reside in a single block of memory. In C99 the struct would be declared as
struct my_struct {
int n;
char s[];
};
and to create an object you'd have to allocate the whole thing dynamically
struct my_struct *ms = malloc(sizeof *ms + 50 * sizeof *ms->s);
The size of memory block in this case is calculated to accommodate the struct members and the trailing array of run-time size.
Note that in this case you have no option to create such struct objects as static or automatic objects. Structs with flexible array members at the end can only be allocated dynamically in C.
Your assumption about pointer aritmetics being faster then arrays is absolutely incorrect. Arrays work through pointer arithmetics by definition, so they are basically the same. Moreover, a genuine array (not decayed to a pointer) is generally a bit faster than a pointer object. Pointer value has to be read from memory, while the array's location in memory is "known" (or "calculated") from the array object itself.
The use of an array of unspecified size is only allowed at the end of a structure, and only works in some compilers. It is a non-standard compiler extension. (Although I think I remember C++0x will be allowing this.)
The array will not be a separate allocation for from the structure though. So you need to allocate all of my_struct, not just the array part.
What I do is simply give the array a small but non-zero size. Usually 4 for character arrays and 2 for wchar_t arrays to preserve 32 bit alignment.
Then you can take the declared size of the array into account, when you do the allocating. I often don't on the theory that the slop is smaller than the granularity that the heap manager works in in any case.
Also, I think you should not be using sizeof(char*) in your allocation.
This is what I would do.
struct my_struct {
int nAllocated;
char s[4]; // waste 32 bits to guarantee alignment and room for a null-terminator
};
int main()
{
struct my_struct * pms;
int cb = sizeof(*pms) + sizeof(pms->s[0])*50;
pms = (struct my_struct*) malloc(cb);
pms->nAllocated = (cb - sizoef(*pms) + sizeof(pms->s)) / sizeof(pms->s[0]);
}
I suspect the compiler doesn't know how much space it will need to allocate for s[], should you choose to declare an automatic variable with it.
I concur with what Ben said, declare your struct
struct my_struct {
int n;
char s[1];
};
Also, to clarify his comment about storage, declaring char *s won't put the struct on the stack (since it is dynamically allocated) and allocate s in the heap, what it will do is interpret the first sizeof(char *) bytes of your array as a pointer, so you won't be operating on the data you think you are, and probably will be fatal.
It is vital to remember that although the operations on pointers and arrays may be implemented the same way, they are not the same thing.
Arrays will resolve to pointers, and here you must define s as char *s. The struct basically is a container, and must (IIRC) be fixed size, so having a dynamically sized array inside of it simply isn't possible. Since you're mallocing the memory anyway, this shouldn't make any difference in what you're after.
Basically you're saying, s will indicate a memory location. Note that you can still access this later using notation like s[0].
pointer arithmetic is faster than arrays, yes?
Not at all - they're actually the same. arrays translate to pointer arithmetics at compile-time.
char test[100];
test[40] = 12;
// translates to: (test now indicates the starting address of the array)
*(test+40) = 12;
Working code of storing array inside a structure in a c, and how to store value in the array elements Please leave comment if you have any doubts, i will clarify at my best
Structure Define:
struct process{
int process_id;
int tau;
double alpha;
int* process_time;
};
Memory Allocation for process structure:
struct process* process_mem_aloc = (struct process*) malloc(temp_number_of_process * sizeof(struct process));
Looping through multiple process and for each process updating process_time dyanamic array
int process_count = 0;
int tick_count = 0;
while(process_count < number_of_process){
//Memory allocation for each array of the process, will be containting size equal to number_of_ticks: can hold any value
(process_mem_aloc + process_count)->process_time = (int*) malloc(number_of_ticks* sizeof(int));
reading data from line by line from a file, storing into process_time array and then printing it from the stored value, next while loop is inside the process while loop
while(tick_count < number_of_ticks){
fgets(line, LINE_LENGTH, file);
*((process_mem_aloc + process_count)->process_time + tick_count) = convertToInteger(line);;
printf("tick_count : %d , number_of_ticks %d\n",tick_count,*((process_mem_aloc + process_count)->process_time + tick_count));
tick_count++;
}
tick_count = 0;
the code generated will be identical (array and ptr). Apart from the fact that the array one wont compile that is
and BTW - do it c++ and use vector

Creating an Instance of a struct

I have this struct
struct FluxCapacitor{
unsigned char* c_string;
unsigned int value;
};
Now I need to create an instance of this struct. I googled this problem and found that I have to use something like this
typedef struct FluxCapacitor{
unsigned char* c_string
unsigned int value;
};
But I dont really understand the next step with malloc(). Can someone explain it to me?
You do not need malloc() to create an instance of a struct. And I would recommend that you avoid typedefing structures merely to reduce keystrokes. The extra keystrokes would only be saved in declarations and function prototypes (and maybe if you need to cast something), since you don't need the struct keyword elsewhere; the advantage is that when you see struct FluxCapacitor, you know exactly what it is. If you only see FluxCapacitor alone, you don't know if it is a typedef for a struct, or a union, or an integer type or what.
Note that the posted code was missing the semicolon at the end of the declaration. Also, it is unclear why you have unsigned char* c_string;. This may not allow assignment to a string literal. I have changed this in the code below. You can create a single struct like this:
struct FluxCapacitor
{
char *c_string;
unsigned int value;
};
...
struct FluxCapacitor fcap_1;
You can then assign values to the fields of fcap_1:
fcap_1.c_string = "McFly";
fcap_1.value = 42;
Note that you could also use designated initializers at the point of declaration:
struct FluxCapacitor fcap_2 = { .c_string = "Biff",
.value = 1985
};
If you need an array of FluxCapacitor structures, just declare one:
struct FluxCapacitor fcaps[2];
You can assign to the fields of each array member in a loop:
struct FluxCapacitor fcaps[2];
char *somestrings[] = { "McFly", "Biff" };
unsigned somevalues[] = { 42, 1985 };
for (size_t i = 0; i < 2; i++) {
fcaps[i].c_string = somestrings[i];
fcaps[i].value = somevalues[i];
}
Alternatively, you can use designated initializers here too:
struct FluxCapacitor fcaps[2] = { { .c_string = "McFly", .value = 42 },
{ .c_string = "Biff", .value = 1985}
};
Using malloc()
Since OP seems determined to use malloc(), it would be good to first recall that memory allocated with malloc() must later be deallocated with free(). Also note that malloc() can fail to allocate memory, returning a null pointer. Thus the result of a call to malloc() must be checked before attempting to dereference this pointer. The additional complexity should be avoided in favor of the above approaches unless OP has good reason to do manual allocation.
In the code below, the function create_flux_cap() takes a string and an unsigned int as arguments, and returns a pointer to a newly allocated FluxCapacitor structure with the arguments assigned to the appropriate fields. Note that since the FluxCapacitor structure is accessed through a pointer, the arrow operator is used instead of the dot operator.
Inside the function, the return value from the call to malloc() is checked before attempting assignment. If the allocation has failed, no assignment is made and a null pointer is returned to the calling function. Note that in the call to malloc(), the result is not cast, since there is no need for this in C and it needlessly clutters the code. Also observe that an identifier is used instead of an explicit type with the sizeof operator. This is less error-prone, easier to maintain if types change in the future, and is much cleaner code. That is, instead of this:
new_fcap = (struct FluxCapacitor *)malloc(sizeof (struct FluxCapacitor));
use this:
new_fcap = malloc(sizeof *new_fcap);
In main(), the return values from the calls to create_flux_cap() are checked. If an allocation has failed, the program exits with an error message.
The stdlib.h header file has been included for the function prototypes of malloc() and exit(), and also for the macro EXIT_FAILURE.
#include <stdio.h>
#include <stdlib.h>
struct FluxCapacitor
{
char* c_string;
unsigned value;
};
struct FluxCapacitor * create_flux_cap(char *, unsigned);
int main(void)
{
struct FluxCapacitor *fcap_1 = create_flux_cap("McFly", 42);
struct FluxCapacitor *fcap_2 = create_flux_cap("Biff", 1985);
/* Check for allocation errors */
if (fcap_1 == NULL || fcap_2 == NULL) {
fprintf(stderr, "Unable to create FluxCapacitor\n");
exit(EXIT_FAILURE);
}
/* Display contents of structures */
printf("%s, %u\n", fcap_1->c_string, fcap_1->value);
printf("%s, %u\n", fcap_2->c_string, fcap_2->value);
/* Free allocated memory */
free(fcap_1);
free(fcap_2);
return 0;
}
struct FluxCapacitor * create_flux_cap(char *str, unsigned val)
{
struct FluxCapacitor *new_fcap;
new_fcap = malloc(sizeof *new_fcap);
if (new_fcap != NULL) {
new_fcap->c_string = str;
new_fcap->value = val;
}
return new_fcap;
}
You need malloc for dynamic allocation of memory.In your case, both the types char and int are known to the compiler, it means the compiler can know the exact memory requirement at compile time.
For e.g. you can create a struct object like in the main function
#include<stdio.h>
#include<stdlib.h>
struct FluxCapacitor{
unsigned char* c_string;
unsigned int value;
};
int main() {
FluxCapacitor x;
x.c_string = "This is x capacitor"
x.value = 10
}
The x is of value type. You can make a copy and pass around this value. Also, observe we are using . notation to access its member variables.
But this doesn't happen at all time. We are not aware of future FluxCapacitor requirement and so above program will need more memory as while it is running and by using the malloc we can ask the compiler to provide us requested memory. This is a good place to use malloc, what malloc does is, it returns us a pointer to a piece of memory of the requested size. It is dynamic memory allocation.
Here's a simple example: let suppose if you need struct declaration of FluxCapacitor but don't know how many you will need, then use malloc
#include<stdio.h>
#include<stdlib.h>
typedef struct FluxCapacitor {
unsigned char* c_string;
int value;;
} flux;
// typedef is used to have the alias for the struct FluxCapacitor as flux
int main() {
flux *a = malloc(sizeof(flux)); // piece of memory requested
a -> c_string = "Hello World"; // Pointer notation
a -> value = 5;
free(a); // you need to handle freeing of memory
return 0;
}
.

What is the difference between using malloc to allocate memory to a struct pointer and pointing a struct pointer to a struct's memory address?

What is the difference between these two snippets of code?
// Structure
struct file {
int fileSize;
};
int main(void) {
// Variables
struct file *pFile = (struct file*) malloc(sizeof(struct file)); // Declare pointer of type struct file and allocate enough room
pFile->fileSize = 5;
free(pFile);
return 0;
}
and
// Structure
struct file {
int fileSize;
} file1;
int main(void) {
// Variables
struct file *pFile = &file1; // Declare pointer of type struct file and point to file1 struct
pFile->fileSize = 5;
return 0;
}
Is there something big I'm missing here? I'm thinking maybe face value wise these are the same but the underlying memory allocation is different? I just can't grasp it.
There are several differences here:
With malloc you can repeat the call multiple times, and get new valid memory area for your struct; there is only one statically allocated struct
Memory obtained through malloc needs to be freed at the end; statically allocated memory does not need freeing
Statically allocated struct is visible from multiple functions inside the translation unit; memory from malloc is not shared with other functions unless you pass a pointer to them explicitly.
In your first snippet pFile points to dynamically-allocated memory.
In your second snippet, pFile points to a global variable.
Other than the fact that you need to free the dynamic one yourself (which you haven't by the way), the way you interact with the struct is exactly the same in either case.

How to increase the size of an array in C

I have an array inside a structure as below
struct st
{
....
int index[1];
....
}
How can I increase size of the array present inside structure to say 6, when I want to use the array inside a function.
Probably you looking for struct hack. Struct hack is a technique which allows you allocate additional memory for an array inside struct. Here is an example
struct str {
int value;
char ar[0];
};
int main()
{
struct str *s = malloc( sizeof(struct str) + 20 );
strncpy( s->ar,"abcd", 5);
printf("%s",s->ar);
return 0;
}
As array defined at the end of the struct, s->ar will get those additional 20 bytes added to sizeof(struct str) in malloc.
Edit as Daan Timmer noted, this technique can be applied only to last member of a struct.
You may try this:
struct st { ....
int index[6];
....
}
Also you may check function malloc() and realloc() in C
On a side note:
You may check STL container like std::vector which encapsulate the associated memory management.
An array defined that way exists on the stack. In order to dynamically change the size you will need to use allocate on the heap using malloc realloc and free.

Resources