Allocating memory for structures in c - c

struct data{
char *key;
char *fname;
char *lname;
char *grade;
struct data *next;
};
newnode = (struct data*)malloc(sizeof(struct data));
strcpy(newnode->lname,lname);
strcpy(newnode->grade,grade);
strcpy(newnode->key,key);
strcpy(newnode->fname,fname);
newnode->next=NULL;
So i was working on hashtables. The above code crashes while
struct data *newnode;
newnode = (struct data*)malloc(sizeof(struct data));
newnode->lname=(char*)malloc(strlen(lname)+1);
newnode->fname=(char*)malloc(strlen(fname)+1);
newnode->grade=(char*)malloc(strlen(grade)+1);
newnode->key=(char*)malloc(strlen(key)+1);
strcpy(newnode->lname,lname);
strcpy(newnode->grade,grade);
strcpy(newnode->key,key);
strcpy(newnode->fname,fname);
newnode->next=NULL;
this code seems to run. Why is that? As far as i understand i've already allocated memory for my struct in the heap. Why would i have to do it for each object specifically? Is there something else im missing? Cause i really don't understand why the bottom example would work.

With newnode = (struct data*)malloc(sizeof(struct data)), you allocate memory only for struct data, which is a set of pointers, but you do not allocate any memory for that where these pointers are pointing to and where you will copy your strings to. So you have to allocate memory for each string separately, either by using malloc as in the second part of your question, or by using strdup, which does malloc and strcpy in one command:
struct data{
char *key;
char *fname;
char *lname;
char *grade;
struct data *next;
};
newnode = (struct data*)malloc(sizeof(struct data));
newnode->lname = strdup(lname);
newnode-> grade = strdup(grade);
newnode-> key = strdup(key);
newnode-> fname = strdup(fname);
newnode->next=NULL;
It's worth noting that strdup requires a string as input, i.e. a pointer that is not NULL and that points to a \0-terminated sequence of characters.

When you do
newnode = malloc(sizeof(struct data));
you only allocate memory for the actual structure. But since the structure contains pointers, you need to make those pointers point somewhere valid. The single malloc call doesn't know anything about the contents of the structure, or how much extra memory it should allocate for all the pointers.
If, for example, you declare a single normal pointer variable you would not expect to be able to just use it as a destination for a strcpy call without allocating memory, would you?

When you malloc a structure with char * inside it doesn't point anywhere (at least is NULL) so you've to malloc it as a normal sequence of characters also because you must know the size of the destination string. You can do it in your way using malloc and strcpy or just strdup.

Related

How to free char array in struct

I see that you can free char * pointers within struct but how do you free char[N] inside a struct
typedef struct Edge
{
char number[13];
int numOfCalls;
struct Edge *next;
} Edge;
When I do this i get an error
Edge *edge = malloc(sizeof(Edge));
edge->next = NULL;
strcpy(edge->number,numberOne); // numberOne is also a char[13];
free(edge->number);
free(edge);
If you use char array (char number[13]) in struct, you don't have to malloc or free the array. Once you do malloc for struct Edge, there is also space for number in memory.
In summary, if you use char pointer as a member of struct Edge, you need to malloc or free memory space for char pointer, but you don't have to do that in your case. Therefore, delete free(edge->number) line.
The lifespan of number in the struct Edge is automatic. Even if you dynamically allocate an Edge struct, when you free the struct, you'll free the memory for the char array.

Why don't we use calloc() insted of malloc() while creating linked list in C? [duplicate]

This question already has answers here:
Difference between malloc and calloc?
(14 answers)
Closed 2 years ago.
When we create a Linked List in C. In that, we have to allocate memory Dynamically. So we can use malloc() and calloc(), but most of the time programmers use malloc() instead of calloc(). I don't understand why?
This is a node -
struct node
{
int data;
struct node *next;
};
Now we are intinalizing the ptr -
struct node *ptr = (struct node *)malloc(sizeof(struct node));
Now here we are using malloc() So why most of the programmers don't use calloc() instead of malloc(). What difference does it make?
Consider a more realistic scenario:
struct person {
struct person *next;
char *name;
char *address;
unsigned int numberOfGoats;
};
struct person * firstPerson = NULL;
struct person * lastPerson = NULL;
struct person * addPerson(char *name, char *address, int numberOfGoats) {
struct person * p;
p = malloc(sizeof(struct person));
if(p != NULL) {
// Initialize the data
p->next = NULL;
p->name = name;
p->address = address;
p->numberOfGoats= numberOfGoats;
// Add the person to the linked list
p->next = lastPerson;
lastPerson = p;
if(firstPerson == NULL) {
firstPerson = p;
}
}
return p;
}
For this example, you can see that calloc() may cost CPU time (filling the memory with zero) for no reason at all because every field in the structure is set to a useful value anyway.
If a small amount of the structure isn't set (e.g. numberOfGoats is left as zero), then it's still likely to be faster to set that field to zero instead of setting the whole thing to zero.
If a large amount of the structure isn't set, then calloc() can make sense.
If none of the structure is set, then you shouldn't have allocated memory for nothing.
In other words; for most scenarios, calloc() is worse (for performance).

Understanding dynamic memory allocation of a string within a struct

I have come across an instance where memory is allocated dynamically to a char pointer within a struct in a way that does not make much sense to me, but - of course - works.
A similar question has been posted before. The answers, however, did not help me understand what is actually happening in the allocation process.
Here is the code example I found:
struct a_structure {
char *str;
struct a_structure *next;
};
Memory has been allocated in the following way:
ptr_start=(struct a_structure *)malloc(sizeof (struct a_structure *));
...
char *some_words="How does this work?";
ptr_start->str=(char *)malloc(strlen(some_words)+1);
strcpy(ptr_start->str, some_words);
ptr_start->next=(struct a_structure *)malloc(sizeof(struct a_structure *));
...
I don't understand why malloc is used with the size of a pointer here. ptr_start is a pointer of type struct a_structure. That would mean it needs memory of size sizeof(struct a_structure) + the size of my string that hasn't been specified in the structure declaration. In the above example, however, malloc returns the address of yet another pointer pointing to a structure of type a_structure, am I right?
I don't understand why malloc is used with the size of a pointer here.
ptr_start is a pointer of type struct a_structure. That would mean it
needs memory of size sizeof(struct a_structure) + the size of my
string that hasn't been specified in the structure declaration
You are right. To create structure a_structure in order to manipulate it we need to allocate memory for whole structure.
(Unless the object has been ALREADY created and for whatever reason we need a dynamically allocated pointer holding pointer to that object).
but - of course - works.
The presented fragment of the program cannot work properly for the stated above reasons.
In the above example, however, malloc returns the address of yet
another pointer pointing to a structure of type a_structure, am I
right?
Yes, you are right.
This is also problematic:
ptr_start->next=(struct a_structure *)malloc(sizeof(struct a_structure *));
ptr_start->next can hold a pointer already. We typically do not need to allocate a pointer here. We would assign a pointer to the existing
structure or we would allocate memory for the whole structure.
See example:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
struct a_structure {
char *str;
struct a_structure *next;
};
struct a_structure * allocatePointer(void)
{
// ptr ptrToObj1Allocated points to allocted memory which can hold a ponter
struct a_structure * ptrToObj1Allocated = malloc(sizeof (struct a_structure *));
return ptrToObj1Allocated;
}
int main(){
// 1.
struct a_structure obj1; // structure a_structure has been allocated on the stack
struct a_structure * ptrToObj1 = & obj1; // points to the existing structure
char *some_words = "How does this work?";
ptrToObj1->str = malloc(strlen(some_words)+1);
if(ptrToObj1->str == NULL){printf("No enough memory\n"); return -1;}
strcpy(ptrToObj1->str, some_words); // copy the string
// now obj1 has its own copy of the string.
// 2.
// dynamically allocate another structure on the heap
// we want to allocate memory for the structure not just a memory to keep the pointer to the structure.
struct a_structure *obj2 = malloc( sizeof (struct a_structure)); // memory has been allocated to hold struct a_structure with 2 pointers
if(obj2 == NULL){printf("No enough memory\n"); return -2;}
char *words = "More words..";
obj2->str = malloc(strlen(words)+1);
if(obj2->str == NULL){printf("No enough memory\n"); return -3;}
strcpy(obj2->str, words); // copy the string
obj2->next = ptrToObj1; // points to the already existing object
//----
printf("String in obj1 is: %s\n", ptrToObj1->str);
printf("String in obj2 is: %s\n", obj2->str);
printf("obj2->next points to structure with string: %s\n", obj2->next->str );
// free the allocated memory:
free(ptrToObj1->str);
free(obj2->str);
free(obj2);
return 0;
}
Output:
String in obj1 is: How does this work?
String in obj2 is: More words..
obj2->next points to structure with string: How does this work?
Given that you have struct a_structure* ptr_start, this code is incorrect and does not work:
ptr_start=(struct a_structure *)malloc(sizeof (struct a_structure *));
It should have been:
ptr_start = malloc(sizeof *ptr_start);
The reason why it "seems to work" is because you invoked undefined behavior, and anything can happen. The program could seem to work one moment, then crash at another time.
This does however just allocate the struct itself. The pointers inside it will, like all pointers, point at memory allocated somewhere else. The following code with malloc for the string and strcpy() is one way to do so.
The last line is however incorrect for the same reason as pointed out above.

Allocating a struct and saving a string in it

I'm having issues with getting create to hold firstE here:
struct node {
char * data;
struct node * next;
};
struct node * createList(char * firstE){
struct node *create;
create = malloc(sizeof(struct node));
create->data = malloc(sizeof(struct node));
strcpy(create->data, firstE);
create->next = NULL;
return create;
}
I'm having a problem with the memory allocation for create->data. I am trying to get it to hold the value of FirstE but I can't seem to get it.
I have to guess your problem since there is no struct definition. Your second malloc allocates memory for a field of the same type as the struct. But because you use strcpy to copy from the function argument, I suggest this line is incorrect, it allocates the wrong amount of memory
create->data = malloc(sizeof(struct node));
strcpy(create->data, firstE);
Since you copy the string argument to this field, I suggest this
create->data = malloc(1 + strlen(firstE));
strcpy(create->data, firstE);
The 1 + is to allow for the string terminator.

Segmentation Fault in a struct with a pointer to another struct

I'm having some issues with my linked list. I have struct dListNode used as the nodes for the list with a pointer to struct data, which is used as the data storage.
struct data{
int payload;
};
struct dListNode{
struct dListNode *next;
struct dListNode *prev;
struct data *val;
}*dHead, *dTail;
My program compiles fine, but I get a segmentation fault at the line indicated below. What is going on?
newDNode = (struct dListNode *)malloc(sizeof(struct dListNode)+sizeof(struct data));
printf("newnode created\n"); // this prints
newDNode->val->payload = rand() % 1000; //error here?
printf("newnode payload: %i\n", newDNode->val->payload); //seg fault before this is printed
Also, I have already ran this line in the program: srand((unsigned)time(NULL))
NewDNode doesn't have an associated memory allocation to it. So when you do
newDNode = (struct dListNode *)malloc(sizeof(struct dListNode)+sizeof(struct data));
This just allocates memory to newDnode and not to newDnode->val. Since newDNode->val just contains whatever was leftover in the memory at that location (or maybe even 0 (NULL pointer)), and you try to assign a value to the memory location which is neither on the stack nor on the heap, the program complains because you are trying to access unassigned part of memory.
Here's what you should do:
newDNode = malloc(sizeof(struct dListNode));
newDnode->val = malloc(sizeof(struct data));
printf("newnode created\n");
newDNode->val->payload = rand() % 1000;
printf("newnode payload: %i\n", newDNode->val->payload);
And as a tip, always try to not cast the result returned by malloc (or any other memory allocation function). Its considered bad practice.
You problem is that you never initialized the pointer val:
newDNode->val->payload = rand() % 1000;
newDNode is allocated, but none of the fields are initialized, so dereferencing val will likely cause that segmentation fault.
So you will need to allocate something for val before you access it.
newDNode = malloc(sizeof(struct dListNode)); // Allocate "dListNode"
newDNode->val = malloc(sizeof(struct data)); // Allocate "data"
newDNode->val->payload = rand() % 1000;
You have a slight misunderstanding of how the allocation works. You need to allocate each pointer separately.
EDIT : And alternate approach is just to not use a pointer for val in the first place:
// Declare struct as:
struct dListNode{
struct dListNode *next;
struct dListNode *prev;
struct data val;
}*dHead, *dTail;
// Build object like this:
newDNode = malloc(sizeof(struct dListNode));
newDNode->val.payload = rand() % 1000;
val does not point to a valid data structure. Sure, you malloc enough size, but that doesn't mean that val is now all of a sudden a valid pointer. You should initialize newDNode with just the size of a dListNode and then separately initialize newDNode->val to point to some valid chunk of memory large enough for a data structure.
On a side note, you don't need to cast the return value of malloc. That's a C++ thing; in C a void* can be implicitly converted to any other pointer type.
Second, if you typedef your struct types you don't have to write struct all over the place when using them.
You're never setting newDNode->val to point to anything. So when you try to set newDNode->val->payload, you're dereferencing either a null pointer or some random address (i forget which). Neither case is what you want.
I don't really like the idea of malloc'ing both the structs in the same statement. But if you insist on doing it, you'll need to do something like
newDNode->val = (struct data*)((char*) newDNode + sizeof(struct dListNode));
A better way, though, is to change the struct so that val is a struct rather than just a pointer to one. Then sizeof(struct dListNode) includes the size of struct data, and you can access it like newDListNode->val.payload without having to malloc the data part separately or do any tricky pointer math. (Drawback being, you'd have to copy the structs to store them in an array, swap them around, etc.)

Resources