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.
Related
I'm trying to allocate memory for a pointer, but have a reference to the address of that pointer. I'm still pretty new to C and this is my first time working with double pointers really.
So I have two structures and they look like this:
typedef struct myNodes {
int data;
struct myNodes *next;
} listElement;
typedef struct {
listElement **ptrToElements;
} myStruct;
In another file, I'm trying to dynamically allocate memory for my pointer by doing something like this:
myStruct *myStruct = malloc(sizeof(*myStruct));
*(myStruct->ptrToElements) = (listElement*)malloc(sizeof(listElement));
but I keep encountering a segmentation fault from doing so. What could be the issue? Thanks!
The problem is with
*(myStruct->ptrToElements) ....
statement. Before dereferencing myStruct->ptrToElements, you need to make sure it points to a valid memory.
To elaborate, you allocate memory for myStruct. Fine.
That constitutes allocating memory for the member ptrToElements. Good.
Question: What does ptrToElements points to?
Answer: Indeterministic.
So, when you try to derefernce a pointer which points to an indeterministic memory address, it's pretty much invalid memory address and attempt to do so will invoke undefined behavior.
Solution: You need to allocate memory for myStruct->ptrToElements before you can go ahead and dereference it.
having said that, please see do I cast the result of malloc?
You define the structure to contain a pointer to a pointer to a listElement
typedef struct {
listElement **ptrToElements;
} myStruct;
As Sourav Ghosh wrote, you try to assign a value to the pointer where ptrToElements would point to without allocating memory.
Probably you should change the pointer type to
typedef struct {
listElement *ptrToElements;
} myStruct;
and when allocating the memory
myStruct *myStruct = malloc(sizeof(*myStruct));
/* If the list can be empty, initialize root with NULL pointer */
myStruct->ptrToElements = NULL;
/* when you add the first list element */
myStruct->ptrToElements = malloc(sizeof(listElement));
myStruct->ptrToElements->data = someValue;
/* at least for the last element you add here you should initialize next */
myStruct->ptrToElements->next = NULL;
Don't forget to handle errors, e.g. malloc returning NULL.
I think this is what you want:
typedef struct myNodes {
int data;
struct myNodes *next; // not clear what this pointer is used for...
} listElement;
typedef struct {
listElement *ptrToElements;
} myStruct;
// Memory Allocation
// allocate myStruct pointing to an array of N listElements
myStruct *ms = malloc(sizeof(myStruct));
ms->ptrToElements = malloc(N * sizeof(listElement));
// element access
for (int i = 0; i < N; i++) {
listElement *le = ms->ptrToElements[i];
le->data = ...
le->next = NULL; // not clear what this pointer is used for...
}
// Memory deallocation
free(ms->ptrToElements);
free(ms);
This is my code:-
typedef struct Frame
{
char* name;
unsigned int duration;
char* path; // may need to scan (with fgets)
}frame_t;
typedef struct Link
{
frame_t* frame;
struct Link* next;
}link_t;
void addNewFrame(void)
{
link_t* newLink = (link_t**)malloc(sizeof(link_t*));
printf(" *** Creating new frame ***\n\n");
printf("Please insert frame path:\n");
// newLink->frame->name = (char*)malloc(sizeof(char) * MAX_LEN);
fgets(newLink->frame->name, MAX_LEN,stdin);
printf("%s", newLink->frame->name);
}
I just need to add a data to name variable in the "Frame" link list, please help me by reviewing this code.
You want to allocate the right types here:-
link_t* newLink = malloc(sizeof(link_t)); //Pointer to Link st
if(newLink){
newLink->frame = malloc(sizeof(frame_t)); //Pointer to frame member
if(newLink->frame){
newLink->frame->name = malloc(sizeof(char) * MAX_LEN); //Pointer to name member
if(newLink->frame->name){
//Rest of your code
}
}
}
EDIT:-
1. As pointed out in comments there's no need to cast the pointer returned by malloc()
2. Another very imp point you may want to check validity of the pointers before de-referencing them
First. You don't need to cast void * so (link_t **)malloc(... can be only malloc(....
Second. You allocated enough memory for a pointer not for a struct. I think you mean malloc(sizeof(link_t)) or even better malloc(sizeof(*newLink))
Third newLink->frame is a pointer so you need to allocate data for it too, newLink->frame = malloc(sizeof(frame_t))
Fourth newLink->frame->name is still a pointer so you need to allocate data for it too. newLink->frame->name = malloc(MAX_LEN)
The confusion that you are doing is pretty common. When you say type *something you are allocating a pointer to type in the stack. A pointer needs to point to somewhere else or NULL, or bad things happen. This applies to structures too. If your structure has a pointer member you need to point it to somewhere else. The somewhere else is where the real "type" object resides.
This also applies to arrays. If you say 'int foo[10]' you are allocating ten integers in the stack. If you say int *foo[10] you are allocating ten pointers in the stack. If you say int **foo you are allocating one pointer in the stack. Again all pointers need to be initialized, I mean, they need to point to some valid object, allocated somewhere else in the memory.
I hope this helps.
Some other points.
Always check pointer coming from malloc, if allocation failed you'll receive NULL. Dereferencing NULL will break your program.
Always initialize memory coming from malloc, fill it with zeros or something.
Don't use _t suffix, is POSIX reserved.
I didn't test any of this.
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.
I am confused with the usage of free() in regard to data structures in C.
If I have the following data structure:
struct Person {
char *name;
int age;
float weight;
float height;
};
I am allocating memory for the structure via malloc(), likewise: struct Person *me = malloc(sizeof(struct Person));
After I am done with using my structure (right before ending the program), I proceed to freeing the memory allocated, like this:
free(person_pointer->name);
free(person_pointer);
Freeing the memory that the name pointer points to is necessary to my knowledge, because if I only free person_pointer I only free the memory that was allocated to store the data structure and its members but not the memory that is pointed to by pointers-members of the structure.
However with my implementation valgrind seems to suggest that the first free() is invalid.
So my question boils down to: When I free the memory that a struct occupies via a pointer, should I preemptively free the memory that member pointers point to or not?
EDIT: This is my whole code:
#include <stdio.h>
#include <stdlib.h>
struct Person {
char *name;
int age;
float weight;
float height;
};
int main(int argc, char **argv)
{
struct Person *me = malloc(sizeof(struct Person));
me->name = "Fotis";
me->age = 20;
me->height = 1.75;
me->weight = 75;
printf("My name is %s and I am %d years old.\n", me->name, me->age);
printf("I am %f meters tall and I weight %f kgs\n", me->height, me->weight);
free(me->name);
free(me);
return 0;
}
me->name = "Fotis";
/* ... */
free(me->name);
The rule is:
1 malloc = 1 free
You didn't use malloc on me->name, so you don't have to free it.
BTW, me->name should be of const char * type.
When you do
me->name = "Fotis";
The name pointer is not alloced by malloc, it points to a stack variable which is stored in the strings table of your binary file at compile time, hence you can't free it.
The rule of thumb is : Only free what you have malloced.
You can't update this read-only string though.
If you did something like :
me->name = strdup("Fotis");
Since strdup does a malloc (see the manual), you have to free it, and you can update the string after its creation.
Yes you have to free all the memory of pointers inside the structure if you allocated them.
Also make sure you free the members before you free the structure.
A simple way to remember is free them in the reverse order in which you have allocated.
The problem is that you didn't actually malloc'ed the char * name inside your structure.
struct Person *me = malloc(sizeof(struct Person));
me->name = strdup("Fotis");
...
free(me->name);
free(me);
return (0);
When you write this
me->name = "Fotis";
You don't actually malloc, the pointer name points to a stack variable of type const char *, wich is not malloc'ed.
I am writing a C project with pointers and structs, and right now facing this problem:
There is a structure
struct Customer
{
char Name[80];
char Address[40];
int ID;
int Pnumber;
};
and I am gonna make a dynamic array of this structs with *line_count* number of members. I use this code, but it crashes a program:
struct Customer* ph;
ph = (struct Customer*)malloc(line_count * sizeof(struct Customer));
What am I doing wrong?
Good:
struct Customer* ph;
ph = (struct Customer*)malloc(line_count * sizeof(struct Customer));
Better:
struct Customer* ph =
(struct Customer*)malloc(line_count * sizeof(struct Customer));
if (!ph) {
<<error handling>>
...
But frankly, it sounds like the problem is elsewhere in your code.
There's nothing fundamentally wrong with your malloc().
Maybe "line_count" is bogus, maybe "malloc()" is failing (in which case, it should return "NULL") ... or maybe you're accessing the struct incorrectly and/or failing to initialize it correctly.
A stack traceback of the actual crash would be very useful.
The piece of code you are showing might crash only if ph == NULL after the malloc call and you dereference it.
From the malloc man page:
The malloc() and calloc() functions return a pointer to the allocated
memory that is suitably aligned for any kind of variable. On error,
these functions return NULL. NULL may also be returned by a
successful call to malloc() with a size of zero, or by a successful
call to calloc() with nmemb or size equal to zero.