what is difference between these? - c

I have this function which should copy a node in a linked list(not first of it)
struct Node {
char* data;
Node* next;
};
void Insert(Node*head, int index, char* data) {//find a is function to find needed position
Node* temp = find(head, index);
Node* t = (Node*)malloc(sizeof(Node));
t->data = (char*)malloc(100);//where the problem is //line 4
strcpy(t->data, data);
t->next = temp->next;
temp->next = t;
}
it will work well if line 4 is in my code. I have read this question:
crash-or-segmentation-fault-when-data-is-copied-scanned-read-to-an-uninitializ
so I know pointer cannot contain any data and I cannot copy/store data into a pointer. So, as you see I allocated memory for it first and then placed data in it, otherwise my program will crash.
But then I used this: t->data = data; and it worked, so I want to know: why when I use strcpy like this strcpy(t->data, data);, I need to allocate memory for t->data first, otherwise my program will crash; but this t->data = data; will work well, without the requirement to allocate memory?
Can you explain this to me?
PS:casting malloc is because of using c++ compiler.

When you use the code t->data = data you are not copying any data to your node! All you are doing is make the node's data member point to the data that the function's argument also points to - so, if you later change that data, then you will also change the node's data. This is probably not what you intend! For example, if you call the function several times from 'the outside' and use the same variable to pass the data in, then each of your added nodes will have a data member pointing to the same piece of data.
If you actually want to copy the data from the argument to your new node (as your call to strcpy does), then you must first allocate storage space for it, using (in your code) the malloc function.
But, as mentioned in the comments, the strdup function is much more convenient here: this both allocates the (exact required amount of) memory and copies the data in one fell swoop:
t->data = strdup(data);
Note: The memory allocated by strdup needs to be released (with a call to free) when you're done with it, in just the same way as memory allocated by malloc.

Code only allocated for a size of a pointer when the size of the referenced object is needed.
// Node* t = (Node*)malloc(sizeof(Node*));
Node* t = (Node*)malloc(sizeof(Node));
Even better is to size to referenced object rather than the type. Cast not needed either.
Node* t = malloc(sizeof *t);
String allocation is suspicious too. Rather than a fixed 100, I'd expect an allocation to the size of the string.
//t->data = (char*)malloc(100);
//strcpy(t->data, data);
size_t len = string(data);
t->data = malloc(len + 1);
strcpy(t->data, data);
Robust code would check for allocation errors.
Node* t = malloc(sizeof *t);
if (t == NULL) Handle_OutOfMemory();

Related

how to build object from mmapped memory

I am building a custom allocator. I am calling mmap() the first time and then I am constructing an explicit freelist. Everything works fine, but when I need to split an existing block I do not seem to be able to initialize an object from a void* (my C fundamentals are quite rusty). I know it sounds confusing so here is the code that I have.
// this is the struct I am using to keep track of the free nodes
struct Node {
size_t header;
void* payload;
}
when I split, I decrease the size of the big node
void* split_block(Node* good_node, size_t reqsize) {
DECREASE_SIZE(good_node)
Node* prev_node = (Node*)(good_node -> payload);
Node* next_node = (Node*)((good_node -> payload) + 8);
}
I store the pointers to next and previous node. IMPORTANT, the pointer are inside the payload, specifically prev = payload, next=payload+8.
Now the problem. How do I construct a node from the raw memory (payload).
The code that does not work is this
// I omit the calculation of the address at which
// the split_part is going to end up
Node* split_part = GET_HEADER_POSITION(good_node, reqsize);
split_part->header = some_value;
split_part->payload = prev_node;
split_part->payload[1] = next_node;
I did not construct the object. But how can I do so, should not this work just like when I malloc memory?
Node* node = malloc(sizeof(Node));
Thank you for the attention.

Understanding how freeing a head allocated pointer in structures work in C

So I have this NODE structure
typedef struct tNODE {
struct tNODE* parent;
char* tag;
}NODE;
and I have a free function that goes through all the nodes and frees them.
Also I have a new node function that simply mallocs the amount of a Node structure and sets everything to NULL except parent.
NODE* new_node(NODE* parent){
NODE* result = malloc(sizeof(NODE));
result->inner_text = NULL;
result->parent = parent;
}
My question is that if for example I have the following code
NODE* temp = new_node(parent);
temp->tag = "x"
and
NODE* temp = new_node(parent);
temp->tag = strdup("x");
I can free the strdup("x") version with free(temp->tag) but not the temp->tag = "x". so I have 2 Questions.
1-:Why is this happening ? isnt there a memmory allocated when the new_node function is called ?
2- If I have a code with the first version(that means temp->tag = "x") and I want to free all the nodes, Does that mean that I have to only call free(temp) and the tag will also get free'd ? Thank you
the abbreviated answer is that you cannot free the memory in case of the first example, the detailed reason is that:
in case of the first version when you typed:
NODE* temp = new_node(parent);
temp->tag = "x";
this created a null-terminated string stored in the read-only memory, not the heap memory, to be more specific in the .rodata section of the memory which is just a section of the memory where you can only read but not modify strings, so if you write a code like:
NODE* temp = new_node(parent);
temp->tag = "x";
temp->tag[0] = 's';
the line temp->tag[0] = 's'; will throw a segmentation error as you are trying to modify a memory that can't be modified, that's why they say that the strings are immutable, which means that in case of the first example code, you cannot free the memory pointed by the pointer because the "x" will always be there in the read-only memory at any time of the execution of the program.
in the second case when you wrote:
NODE* temp = new_node(parent);
temp->tag = strdup("x");
you can refer to strdup() manual where they said:
The strdup() function returns a pointer to a new string which is a
duplicate of the string s. Memory for the new string is obtained
with malloc(3), and can be freed with free(3).
which means that the "x" is stored in the heap memory which is modifiable and readable memory, so you can modify it and read it and free it at any time.

Why did my function to insert a node at the beginning of a linked-list fail the second time?

This is my function to add a new node using double pointer
void insertBefore(node_t **first)
{
node_t *new = NULL;
new = (node_t *) malloc(sizeof(node_t));
new->next = *first;
*first = new;
free(new);
}
If I use it once, everything seems to work fine. However, if I use it again, my linked-list is messed up. I have the output image below (same thing happened to my function to insert node to any position).
I tried to put some very specific part of the code, so if you suspect that I must have been doing something wrong at other parts, please tell me.
Any idea what did I do wrong?
The output image
Just remove free(new);. Since new and *first have same value, freeing new also frees *first.
Refined code:
void insertBefore(node_t **first)
{
node_t *new = malloc(sizeof(node_t)); //don't cast
if(!new)
{
fputs("Don't have enough memory", stderr);
return;
}
new -> next = *first;
*first = new;
}
It because you are freeing the memory.
free(new);
You are just assigning the value to first.
*first=new;
Now first and new will point to same memory position. Then you are freeing that memory. Remove the line free(new);.
You free the node you had just allocated; whenever you attempt to use it, undefined behavior will occur because *first becomes a Dangling Pointer. The address stored in the pointer is no longer valid after the function free() returns.
Your code needs many improvements
You don't need to initialize new to NULL; probably no problem as this would be optimized.
You don't need to cast malloc() or in general void * to any other pointer type.
You don't check that malloc() was successful; you should check that new is not being assigned NULL which would indicate an error.
You MUST NOT free() the newly allocated pointer; you should free() it when you don't need it anymore and not immediately after allocating it.
You really should improve your code formatting. It was completely unreadable in the original post.

Correct way to use malloc() and free with linked lists

I am trying to understand malloc() better when it comes to linked list. Does this create memory for the pointer to the list as well as the fields inside of it?
Such as:
SomeStruct * someStructPtr = (SomeStruct *) malloc(sizeof(SomeStruct));
Alongside this, if I am trying to free this node AND the fields inside of it. Do I need to walk through all the fields (see code below). Does this just free the pointer (created from the line above) or does it free the pointer and and the fields.
free(someStructPtr);
For a more direct example. I have a struct of List and I'm trying to allocate space for this struct AND it's fields when it is created. I want to make sure I am creating, deleting, and using stdrup() correctly. My code is below:
Struct Declaration:
typedef struct ListNode_st
{
char * str;
struct ListNode_st * next;
} List;
Create Node:
List * List_createNode(const char * str){
List * listPointer = (List *) malloc(sizeof(List));
//make sure there was enough memory
if(listPointer == NULL)
return NULL;
//malloc for next
listPointer.next = (List *) malloc(sizeof(List *));
if(listPointer.next == NULL)
return NULL;
listPointer.next = NULL;
//malloc for str
listPointer.str = strdup(str);
//make sure enough space for the string to be copied
if(listPointer.str == NULL)
return NULL;
//return value
return listPointer;
}
Delete Node:
void List_destory(List * list){
//base case -- (last item)
if(list == NULL)
return;
//recurse case -- (there are more items)
List_destroy(list->next);
if(list->str != NULL)
free(list->str);
if(list->next != NULL)
free(list->next);
free(list);
}
Please don't cast the return value from malloc().
malloc(sizeof(SomeStruct))
allocates enough memory for one struct, and you then have to initialise every field within the struct.
calloc(1, sizeof(SomeStruct))
does the same but every byte of the struct is initialised to 0. malloc() and calloc() know nothing about your struct, they simply allocate the amount of memory you asked for. They return a void* pointer so that they can be used with any data type, about which they neither know nor care.
When you come to free() the allocated memory, the same applies - free() knows nothing about your struct, or even if it is a struct. It's up to you to free() any memory allocation within that struct, before you free() the memory for the struct. It does not free a struct. It frees the memory where the struct is.
So the answer is yes, you do need to walk through the whole data structure, otherwise any nested memory allocation pointers will be lost, resulting in memory leak.
List * List_createNode(const char * str){
List * listPointer = (List *) malloc(sizeof(List));
if(listPointer == NULL)
return NULL;
listPointer->next = NULL;
listPointer->str = strdup(str);
if(listPointer->str == NULL){
free(listPointer);
return NULL;
}
return listPointer;
}
void List_destory(List * list){
if(list == NULL)
return;
List_destroy(list->next);
free(list->str);
free(list);
}
Let's warm up a little before we tackle your question.
int x = 42;
Where does the memory of x come from? Is it allocated? Where? If this line is inside a function, the answer is: it is an "automatic" variable and the memory it uses is on the stack.
int * y = NULL;
Where does the memory for y come from now? There was no call to malloc() here and yet, y exists.
By now, you should be able to answer the first part of your question. malloc() is not allocating the memory for your pointer in this case.
struct Node
{
struct Node * next;
int value;
};
void InitNode( Node *node, int value )
{
if(NULL != node)
{
node->next = NULL;
node->value = value;
}
}
// Not on HEAP, not on stack! Where?
// This one gets its memory from "initvars" section.
int foo = 69;
int main( int argc, const char * argv[] )
{
struct Node n1; // instance located on stack...
InitNode(&n1); // no malloc() to be seen...
// Instance located on HEAP, but n2, the pointer is located on stack,
// just like an int x = 42 would be.
struct Node *n2 = malloc(sizeof(struct Node));
}
So, obviously in order to de-mystify what malloc() does requires to understand the different types of memory and how to deal with it.
So far we saw "automatic" aka "stack memory", we saw "initvars" memory. And we saw "heap" memory. malloc() is the function you use to allocate memory on the heap.
Last not least, there are yet other types of memory I will not mention here.
Does this create memory for the pointer to the list as well as the fields inside of it?
Given your struct type
typedef struct ListNode_st
{
char * str;
struct ListNode_st * next;
} List;
the following call will create memory for an instance of that struct:
List *l = malloc( sizeof *l ); // note no cast, operand of sizeof
l points to a block of memory large enough to contain two pointers; however, nothing's been allocated for either str or next to point to. You would have to allocate memory for the string and the next node separately:
l->str = malloc( N * sizeof *l->str ); // allocate N characters
or
l->str = strdup( str );
Note that in most linked list implementations, you don't allocate memory for next when you create a new node; that field is meant to point to another, previously allocated node in the list. You will set it when you insert a node following the current node.
Alongside this, if I am trying to free this node AND the fields inside of it. Do I need to walk through all the fields (see code below). Does this just free the pointer (created from the line above) or does it free the pointer and and the fields.
You need to free any allocated members first before deleting the entire node, such as
free( l->str );
free( l );
Freeing l does not free the memory that l->str points to.

Need some help understanding pointers and memory in C

I'm writing a bit of code for a class, but since I have no experience in C I'm a bit unsure of what the code I've written actually does. Particularly what the memory looks like. Here's the relevant bits:
typedef struct listnode *Node;
typedef struct listnode {
void *data;
Node next;
Node previous;
} Listnode;
typedef struct listhead *LIST;
typedef struct listhead {
int size;
Node first;
Node last;
Node current;
} Listhead;
#define HALLOCSIZE 50
static LIST hallocbuf[HALLOCSIZE];
static LIST *hallocp = hallocbuf;
LIST *CreateList()
{
if(hallocbuf + HALLOCSIZE - hallocp >= 1)
{
LIST temp;
temp->size = 0;
temp->first = NULL;
temp->last = NULL;
temp->current = NULL;
*hallocp = temp;
return hallocp;
}else
return NULL;
}
So my question is, in the CreateList function, how is the program allocating memory for temp? And does the code *hallocp = temp copy the temp LIST into the hallocbuf array? I am trying to have all my LIST structs sit in the allocated memory for hallocbuf. Is this what I'm doing? I'm a bit uncertain of how the typedef, structs and pointers play together.
Thanks!
So my question is, in the CreateList function, how is the program allocating memory for temp?
It isn't, which is a problem. It should do something like this:
temp = malloc(sizeof(Listhead));
And does the code *hallocp = temp copy the temp LIST into the hallocbuf array?
It copies the pointer that was saved in temp into the first element of hallocbuf (assuming that hallocp hasn't been changed anywhere and still has the value that it has been initialized to, pointing to hallocbuf[0]).
Generally it's not usually a good idea to hide the fact that LIST and Node are pointers behind typedefs. It's much clearer where memory needs to be allocated of freed if it's obvious which variables are pointer, and having an explicit * in the variable declaration makes that clear.
temp is allocated in the space used for objects with "automatic storage duration" - this is usually on a runtime stack, but you don't really need to know the details. The space is deallocated when the block in which it was allocated is exited (in your case, when you hit the return).
The line *hallocp = temp; does indeed copy the value of temp into the memory that hallocp is pointing at, which is hallocbuf[0].
The problem is that temp is just a pointer itself - and it's not pointing at anything. This is called a "dangling pointer". This means that when you try to access what it's pointing at, you have an error. That happens in these lines:
temp->size = 0;
temp->first = NULL;
temp->last = NULL;
temp->current = NULL;
You can't have your structs sit in the memory allocated for hallocbuf, because it doesn't have room for structs - it's just an array of pointers, not an array of structs.
If LIST were
typedef struct listhead LIST;
and you accessed temp
temp.size = 0;
...
then
*hallocp++ = temp;
would use hallocp as a pointer into the hallocbuf buffer and place the newly initialized element there. Not the best way to do it, though. You could replace temp with
hallocp->size = 0;
...
++hallocp;

Resources