Why does pointer to malloc'd area fail unless copied? - c

I have a pointer to a struct. I call a routine that determines whether I need this struct and allocates space for it using malloc, returning the pointer to that area or zero if unused.
struct node *node_p;
node_p = need_this();
This works and I can properly access all the elements of the struct. One of the elements of struct node is *next which points to the next node struct and a pointer to a string but it's returning a pointer to a string that doesn't even exist in this routine.
node_p=find_string(node_p->next,"string");
However, this does return a pointer in the struct to the correct string.
struct node *node_p, *node_copy;
node_copy=find_string(node_p->next,"string");
The only difference is using a second pointer instead of the original. Am I doing something wrong here or must it be deeper into the called function? The problem with blaming the called function is I use it in multiple places for months without issue, however the other calls only look for the string and never go to 'next'.
EDIT: Further debugging has shown the problem actually lies with the pointer being passed to find_string and not the returned pointer. That changes the question and the problem so I need to open another question.

In this snippet:
struct node *node_p, *node_copy;
node_copy=find_string(node_p->next,"string");
you dereference node_p when it is not yet initialized (doesn't point to a legally allocated memory block). That's undefined behavior. You should set node_p to a legally allocated memory block of appropriate size first.

You need to allocate memory explicitly for every struct, i.e. allocate a new struct and set next pointer to point to it.
Pointers in C prior to initialization point to random place and you never should dereference them. Safe policy would be to init them to be NULLs.

Related

How to release a struct that wasn't called with malloc?

Assume I have a struct node like such:
struct node {
struct other_struct value;
int some_num;
}
I have seen snippets of code where the struct can be initialized without calling malloc, like this:
struct node my_node;
my_node.value = NULL;
my_node.some_num = 2;
And then value can later be malloced. However, how would I free my_node?
my_node is allocated on the stack, and once it goes out of scope, its memory is automatically deallocated.
Use malloc if you want to allocate something on the heap, and it will persist until you free it. For your example, you would do:
struct node *my_node = malloc(sizeof(struct node));
my_node->some_num = 2;
// Sometime later
free(my_node);
Space will also be allocated for the value field if you malloc (as long as you pass the right size) or if you declare on the stack. sizeof(struct node) includes the size of other_struct.
Currently with those code snippets you can't really free value or my_node, as they're both just static variables, if in your node structure, the other_struct field was a pointer, then you could dynamically allocate some memory, and save the address in that pointer.
Then when done, free the pointer value.
If then, my_node was also a pointer (which I think is what you want), you would need to allocate memory for the node struct, and save the address to the pointer my_node. THEN, allocate some memory for the other_struct struct and save it to the pointer value. And after you're done, you would free value FIRST, then free my_node.
When doing things like this, I generally create a little constructor/destructor function, which will do it all for me. It can be too easy to forget to free the inner pointer (value) and just free the outer pointer (mynode). Then that would cause a memory-leak, as value would still be allocated and taking up room in memory.
The code:
struct node {
struct other_struct value;
int some_num;
};
defines value to be a member of struct node. It is a part of struct node. Whenever a struct node is created, it will contain the member named value, and no other memory needs to be allocated for value. Whether a struct node is created automatically or by malloc or other means, its memory will always include memory for value.
If you changed it to:
struct node {
struct other_struct *value;
int some_num;
}
then value would be a pointer to a struct other_struct, and you would need to provide memory for it to point to.
In this code:
struct node my_node;
my_node.value = NULL;
my_node.some_num = 2;
the object my_node is created automatically, and you do not have to do anything to release it or its members; that will happen automatically. You cannot use my_node.value = NULL because value is a structure, not a pointer.
If the structure definition is changed so that value is a pointer, then you can set to NULL, or you can set it to point at an existing object, or you can allocate memory for it and set it to point to the allocated memory. If you allocate memory for it, then you should ensure that memory is later freed (except it is okay not to free it if you are intentionally keeping it to the end of program execution anyway, and you are executing in user mode on a general-purpose operating system).
You don't free it... it is destroyed, when the block it has been declared in is abandoned by the program.
Let's say that this variable is defined at the beginning of a function's body block. When the function is being called, the function creates this variable as it's a local. When the function terminates, all local variables are destroyed, so it is your local structure.
If you declare such a variable out of any function, then your variable has global duration, and it is created at program initialization, and lives as much as the program itself.

Will a pointer declaration to a structure allocate memory for its members?

check the image of program on turbo c++
output of program
#include< stdio.h>
struct node {
int data;
};
int main() {
struct node *ptr;
ptr->data=3;
printf("%d",ptr->data);
return 0;
}
Output: 3
My question is that even though I have not declared an instance of structure node.
e.g struct node n;
Also I have not assigned memory for ptr using malloc, it still allocates space for ptr->data. Why?
Shouldn't it just assign memory for address ptr on stack.
And where this memory for data field is allocated, on stack or heap.---------
In your code, ptr->data=3; invokes undefined behavior, as ptr does not point to any valid memory location.
You need to make sure that ptr points to a valid memory location before making any attempt to de-reference it.
It appears to work properly in your case, that is also one of the most dangerous side effects of undefined behavior.
That said, ptr is having automatic storage. The memory it would point to, will depend on the allocation used. C standard does not have a notion of stack or heap - that is dependent on the implementation.
Also I have not assigned memory for ptr using malloc, it still allocates space for ptr->data.
Nothing's been allocated. Without an initializer, the value of ptr is indeterminate, and in this case just happens to point to memory that you can write to without immediately crashing your program. You managed to not overwrite anything "important", but that's a matter of luck more than anything else.
You should get in the habit of initializing pointers as you declare them, either as NULL or as the result of the & operator or as the result of a malloc/calloc/realloc call.
When you are creating the pointer struct node *ptr; it will be placed on your stack.
The place where this variable is placed can be anywhere in your stack.
For example it is placed on address 0x100.
When the variable is placed on that location, the data that is there is not set to 0.
So on address 0x100 was the data 0x200 for example, you will have a struct node *ptr pointing to the address 0x200.
Then at that point you are doing the following ptr->data=3; As the code thinks that there is a struct node placed at your address 0x200, it will fill the variable data in there. So on the address 0x200 will the value 3 be written.
When you are in luck (well actually it isn't really luck, as it could cause lots of problems later on) the writing of the value 3 at the address 0x200will not cause any problems, because the memory at address 0x200 wasn't used.
But keep in mind that your code only THINKS that the struct node was placed at that location, but actually there isn't one, so any other variable could be on that location. And when there is a different variable on that address. when you write the value 3 to that address you are you are overwriting the value of that variable. And that could create some very strange behavior in your code.

free(struct variable) doesn't clear previous stored values associated with that variable when I malloc again?

I created a struct like the following:
typedef struct header{
int hc;
char src[18];
char dst=[18];
char reason[15];
char d[3];
char m[3];
char y[4];
struct measurements{
char h_ip[17];
int h_ttl;
int h_id;
float h_rtt;
}HOPS[100];
}HEADER;
INSIDE MAIN:
HEADER *head;
for(...){
head=(HEADER*) malloc(sizeof(HEADER));
.....
free(head);
}
Will the above malloc automatically allocate memory for the inner struct as well? Also, I'm facing a weird problem here. After I free the header, I'm still able to print the values of head->HOPS[i].h_ip. Should I explicitly free the inner struct as well so that even the values get cleared?
Yes, it allocates memory for the inner structure. And you need not free the inner structure separately.
If you have a pointer defined inside your structure, in that case you have to allocate separately for that pointer member of the structure and free that separately.
Consider freeing memory as a black box. All what you know is that after freeing you shouldn't refer to freed memory.
You may find that that memory block still exists and still contains some old values. That's ok: it just was marked as freed and probably it will be used again soon by allocator.
For example when you call malloc again and realized that just allocated block contains values from the old structure. It happens and that's alright. Just use this block as usually.
So, after the problem with the wrong declaration of head was resolved:
free returns a previously allocated memory block to the heap. It does not clear anything (for performance reasons). However, you are not supposed to access that block anymore afterwards. Doing so results in undefined behaviour and might let your computer fly out of the window.
Worst that can happen is ... nothing ... Yes, you might even not notice anything strang happens. However, that does not mean your program run correctly, it just does not show any symptoms.
To catch illegal accesses, you might set the pointer to NULL once you freed the object it points to. Some operating systems catch accesses to addresses near the null pointer address, but there is no guarantee. It is a good practice anyway and does no harm.
For your other question: malloc allocates a block of memory large enough to store that many bytes you passed as argument. If it cannot, it will return a null pointer. You should always check if malloc & friends returned a valid pointer (i.e. not a null pointer).
int *p = malloc(sizeof(int));
if ( p == NULL ) {
error: out of memory
}
...
Notice the omission of the cast of the result of malloc. In C you should not cast void * as returned by malloc & friends (but also elsewhere). As much as you did not for free(head). Both take the same type: void *, btw. (so why cast one and not the other?). Note that in C any object pointer can freely be assigned to/from void * without cast. Warning functions are no objects in the C standard!
Finally: sizeof(HEADER) returns the size of the struct. Of course that include all fields. A nested struct is a field. A pointer to another struct is a field. For the latter, however note: the pointer itself is a field, but not what it points to! If that was another struct, you have to malloc that seperately **and also free seperately (remember what I wrote above).
But as you do not have pointer inside your struct, that is not your problem here. (keep it in mind, if you continue programming, you will eventually need that!)

Trouble with structs and strings

I made a linked list whose nodes hold 4 string values. When I call the newNode function, an error says 'Node has no member named familyName', as well as the other members. My code:
I am really confused with how strings work in structs.
Your immediate problem is the type definition. You cannot call malloc() from within there, all you can do is define the fields. The memory allocation must come later. So, it should be:
typedef struct node{
char *familyName;
char *firstName;
char *address;
char *phoneNumber;
struct node *link;
}Node;
You'll strike another problem (run-time rather than compile-time) once you fix that. When you do something like:
p -> familyName = famName;
that simply copies the pointer into your structure, and the pointer is always the memory location of familyName in main().
That means every node will point to the same memory, and you're continuously updating that memory.
You won't notice the problem with the code as it stands, since you're only asking for one record. But it will become an issue when you start looping to get more records.
Your best bet is to use something like strdup() to make a copy of the string passed in, then each node will have its own memory location for strings:
p -> familyName = strdup (famName);
(don't forget to also free() the memory for each field once you're finished with it).
In the unlikely event your C implementation doesn't have a strdup(), see here.
There are several problems:-
It is not allowed to allocate memory when declaring a structure. Either, do the malloc inside your newNode() method Or, declare the structure like char familyName[50].
Result of malloc should not be casted.
It is better to use strcpy (or strdup) when copying strings

can we use a pointer freed earlier?

I have a question regarding free() in C.
Suppose I have a pointer to some struct (say node *ptr).. after freeing it can i Initialize it to NULL and make it point to some new location using malloc() or realloc()?
For Example:
node *ptr=NULL;
ptr=realloc(ptr,sizeof(node)); //works exactly like malloc
/* Do some operations on ptr */
free(ptr);
ptr=NULL;
ptr=realloc(ptr,sizeof(node));
Is that valid, or will it create a problem.
The reason I used realloc in place of malloc is because all my realloc() calls are in a loop (so instead of sizeof(node) in the second argument it is actually n*sizeof(node) where n keeps on incrementing... and the last location in this resultant array is written with new data) where the memory pointed to by ptr keeps on increasing until the loop ends, at which point I do not require the data in the memory pointed to by ptr, so I think it best to free it. Now, all this is nested in one more bigger(outer) loop.
Thanks a lot for your help
It is ok - you are not really reusing the pointer but just the variable holding the pointer.
ptr doesn't remember that it was once assigned a value, and re-using it again if it was assigned NULL is no different from using it the first time around.
And since realloc() acts like malloc() when it's passed a NULL pointer, it should work just fine.
You should not thinking about it as "freeing the pointer", but freeing whatever the pointer points to. It's perfectly normal that a pointer points first to one object (which may then be freed), and then to another object.

Resources