I've been trying to learn C by myself after basic Java knowledge and I'm trying to implement a linked list. I'm running into trouble when making a createList function - a function that's supposed to make an empty list. I'm having a bit of a weird problem with passing pointers though. These are just snippets of the code, and my definitions of the node / list are located in a header file given by a book CD (so that's not the problem)
LList* createList(void){
LList list;
list.first = NULL;
printf("List from mk_list: \nfirst:%d\nlist address:%d\n",list.first,&list);
return &list;
} //This prints 0 and then the address of list
void print_list(LList *list){
printf("\nList from print_List\nFirst%d\nAddress:%d\n", list->first,list);
} //This prints some random non-null address for some reason, but also the
//SAME address as the list from createList. Why does list->first not print as 0?
int main(void)
{
LList*newList = createList();
printf("\nList from main:\nFirst:%d\nAddress:%d\n", newList->first,newList);
print_list(newList);
system("pause");
return 0;
} //Prints same exact thing as the printf in the createList.
return &list;
list resides on stack and its lifetime completes as function returns. So, using a pointer to it invokes undefined behavior.
Create the object on heap.
Here is your problem:
LList* createList(void)
{
LList list;
...
return &list;
}
Variable list is allocated on the stack, whenever you enter the code of function createList.
Whenever this function (or any other function for that matter) is called, the stack is in a different status.
Sometimes it's 75% full, sometimes only 24% (this is just a figure of speech though).
Your local variable is allocated at the next free slot in the stack, so it doesn't have a constant address throughout the lifetime of your program, but only during the execution of the function itself.
Shorty after the function returns, some other local variable might be allocated in the same address.
Hence, there is no point in returning this address, as you are doing in your code.
UPDATE:
One optional solution for you is to declare LList newList in main, and pass &newList to createList instead of returning a value from that function:
void createList(LList* list)
{
list->first = NULL;
printf("List from mk_list: \nfirst:%d\nlist address:0x%X\n",list->first,list);
}
P.S.: You should probably name this function initList instead.
Related
I have numbers in a linked list which i am supposed to convert to char* and return .
Here is is the function where the problem probably exists.
char* int_str(struct Node** head,char* result) //head is pointer to singly linked list
{
struct Node* temp = *head;
char* string1="";
char* str;
while(temp != NULL)
{
string1=myitoa(temp->data,string1); // myitoa() works fine
str=(char*)malloc(1+strlen(string1));
strcpy(str,string1);
strcat(result,str);
temp=temp->next;
}
return result;
}
The last call to temp->data always ends up having unknown garbage values . (The linked list is built correctly as printing the linked list works properly.)
Example : the linked list is 1->2->3
The last call to temp->data in the function gives 50(some garbage value)
ie 1->2->50
while in the main function the list correctly gives 1->2->3
The last variable ends up as garbage in this function but shows correctly in main function why ?
char* string1;
This declares a pointer but does not allocate a buffer for the string. It's a bit confusing that this uninitialized pointer is passed to myitoa, because myitoa can not do anything with it without causing undefined behaviour.
This line always allocates 5 bytes on 32 bit systems:
str=(char*)malloc(1+sizeof(string1));
sizeof(string1) is the size of the pointer, not of the string. Use
str=(char*)malloc(1+strlen(string1));
instead, or, even better, use
str=malloc(1+strlen(string1));
because the result of malloc should not be casted.
This piece of code will most probably do the job. There is no need to malloc. str is defined as an array of 20 chars. This is where the number in ASCII is stored.
char* int_str(struct Node** head,char* result) //head is pointer to singly linked list
{
struct Node* temp = *head;
char str[20];
while(temp != NULL)
{
strcat(result, myitoa(temp->data, str));
temp=temp->next;
}
return result;
}
I don't think that the problem lies in string manipulations. Most probably it is related to the creation of linked list. Try this:
First of all, try printing the value of temp->data in the loop. Possibly it should be garbage (in which case the list creation contains problem). If the printed value is correct, then check if the "result" string which is being returned, holds the same value or not. If not, then the problem is in myitoa function.
Here I am assuming that myitoa is allocating memory to string1.(if not, then you have to allocate some memory to it either before passing it to function or inside myitoa.
I am implementing Singly Linked List on my program. Now I have this display function to display what is inside my singly linked list. Now the problem is when I call my display function. It only prints the head. For example 20-->NULL. Display function for checking if I implement Singly linked list correctly.
struct node
{
int data;
struct node *next;
}*start=NULL;
void display()
{
struct node *new_node;
printf("The Linked List : ");
new_node=start;
while(new_node!=NULL)
{
printf("%d--->",new_node->data);
new_node=new_node->next;
}
printf("NULL");
}
void creat(int num)
{
struct node *new_node,*current;
new_node=malloc(sizeof(struct node));
new_node->data=num;
new_node->next=NULL;
if(start==NULL)
{
start=new_node;
current=new_node;
}
else
{
current->next=new_node;
current=new_node;
}
//printf("%d->",new_node->data);
}
void main()
{
int binrange,max=100,n,i,divi;
int inp[4];
clrscr();
printf("enter 5 numbers: ");
for(i=0;i<5;i++)
{
scanf("%d",&inp[i]);
}
printf("\nenter range: ");
scanf("%d",&binrange);
n=max/binrange;
divi=max/n;
for(i=0;i<=max;i++)
{
if(i%divi==0 && i>0)
{
//create nodes here
//store i into nodes
creat(i);
}
}
display();
getch();
}
The variable current is a local variable inside the creat function, and it goes out of scope (and "disappears") every time the creat function exits.
That means two things: The variable will always be uninitialized everytime you call the function, and by dereferencing the (uninitialized) pointer you have undefined behavior.
The reason for the undefined behavior is just because the variable is uninitialized. Uninitialized non-static local variables have an indeterminate value, and in reality if will be seemingly random. So what you are doing is taking this pointer that points to a "random" location and write to it.
There are three possible solutions: One is to make the current variable static, the other is to make it global, and the third is to not have it at all and find the end every time the function is called. Oh, and if you go for one of the two first, you should probably rename it to end (or something similar) because that's what it is, a pointer to the end of the list.
In your code, you're defining
int inp[4];
and then you're reading
for(i=0;i<5;i++)
{
scanf("%d",&inp[i]);
}
Clearly past the allocated memory when i is 4 [array indexing in c starts from 0]. So, undefined behaviour.
EDIT:
Also, as Mr. Joachim Pileborg mentioned, struct node * current is local to the creat() function, as goes out-of-scope each and every time the function is finished.
Side Effects:
Every time you start with a fresh current having garbage [you did not initialize].
You'll be dereferencing uninitialized memory.
You need a way to store the value. Otherwise, again, UB.
P.S - Both the cases cause UB in their own ways. :-)
My question is an extension of this: Returning pointer to a local structure
I wrote the following code to create an empty list:
struct node* create_empty_list(void)
{
struct node *head = NULL;
return head;
}
I just read that returning pointers to local variables is useless, since the variable will be destroyed when the function exits. I believe the above code is returning a NULL pointer, so I don't think it's a pointer to a local variable.
Where is the memory allocated to the pointer in this case. I didn't allocate any memory on the heap, and it should be on the stack, as an automatic variable. But what happens when the code exits (to the pointer), if I try to use it in the program, by assigning this pointer some pointees / de-referencing and alike?
struct node* create_empty_list(void)
{
struct node *head = NULL;
return head;
}
is equivalent to:
struct node* create_empty_list(void)
{
return NULL;
}
which is perfectly fine.
The problem would happen if you had something like:
struct node head;
return &head; // BAD, returning a pointer to an automatic object
Here, you are returning the value of a local variable, which is OK:
struct node* create_empty_list()
{
struct node* head = NULL;
return head;
}
The value of head, which happens to be NULL (0), is copied into the stack before function create_empty_list returns. The calling function would typically copy this value into some other variable.
For example:
void some_func()
{
struct node* some_var = create_empty_list();
...
}
In each of the examples below, you would be returning the address of a local variable, which is not OK:
struct node* create_empty_list()
{
struct node head = ...;
return &head;
}
struct node** create_empty_list()
{
struct node* head = ...;
return &head;
}
The address of head, which may be a different address every time function create_empty_list is called (depending on the state of the stack at that point), is returned. This address, which is typically a 4-byte value or an 8-byte value (depending on your system's address space), is copied into the stack before the function returns. You may use this value "in any way you like", but you should not rely on the fact that it represents the memory address of a valid variable.
A few basic facts about variables, that are important for you to understand:
Every variable has an address and a value.
The address of a variable is constant (i.e., it cannot change after you declare the variable).
The value of a variable is not constant (unless you explicitly declare it as a const variable).
With the word pointer being used, it is implied that the value of the variable is by itself the address of some other variable. Nonetheless, the pointer still has its own address (which is unrelated to its value).
Please note that the description above does not apply for arrays.
As others have mentioned, you are returning value, what is perfectly fine.
However, if you had changed functions body to:
struct node head;
return &head;
you would return address (pointer to) local variable and that could be potentially dangerous as it is allocated on the stack and freed immediately after leaving function body.
If you changed your code to:
struct node * head = (struct node *) malloc( sizeof( struct node ) );;
return head;
Then you are returning value of local value, that is pointer to heap-allocated memory which will remain valid until you call free on it.
Answering
Where is the memory allocated to the pointer in this case. I didn't
allocate any memory on the heap, and it should be on the stack, as an
automatic variable. But what happens when the code exits (to the
pointer), if I try to use it in the program, by assigning this pointer
some pointees / de-referencing and alike?
There is no memory allocated to the pointer in your case. There is memory allocated to contain the pointer, which is on the stack, but since it is pointing to NULL it doesn't point to any usable memory. Also, you shouldn't worry about that your pointer is on the stack, because returning it would create a copy of the pointer.
(As others mentioned) memory is allocated on the stack implicitly when you declare objects in a function body. As you probably know (judging by your question), memory is allocated on the heap by explicitly requesting so (using malloc in C).
If you try to dereference your pointer you are going to get a segmentation fault. You can assign to it, as this would just overwrite the NULL value. To make sure you don't get a segmentation fault, you need to check that the list that you are using is not the NULL pointer. For example here is an append function:
struct node
{
int elem;
struct node* next;
};
struct node* append(struct node* list, int el) {
// save the head of the list, as we would be modifying the "list" var
struct node* res = list;
// create a single element (could be a separate function)
struct node* nn = (struct node*)malloc(sizeof(struct node));
nn->elem = el;
nn->next = NULL;
// if the given list is not empty
if (NULL != list) {
// find the end of the list
while (NULL != list->next) list = list->next;
// append the new element
list->next = nn;
} else {
// if the given list is empty, just return the new element
res = nn;
}
return res;
}
The crucial part is the if (NULL != list) check. Without it, you would try to dereference list, and thus get a segmentation fault.
I'm a little unclear on this part of C, since it's a bit unlike other languages I've used, but this may just be a dumb question. I'm trying to implement a stack. I have the node struct, it has the information I want to pass:
struct position{
int square[2];
int counter;
struct position *prev;
};
so in main, I declare and initialize the bottom node of the stack, set *prev to NULL, then declare the rest. My question is, what happens when I try to pass it to function pop? I can create a position object that points to this one and return that, but will it be pushed off the stack when the function closes? Or should I return the position and set that equal to a new position object in main? What if I decide to create several of these nodes in a function? Will they remain once the function closes?
Edit: mah reminded me of my followup question which is, if they don't exist outside of the function, should I use malloc to create the space in the memory for them?
The lifetime of your objects depend on where they're created; if you declare for example a structure within a block of code (where a block is everything inside { and its matching }), that structure is no longer valid once execution leaves the block. Pointers to that structure are only valid as long as the structure is valid.
For what you're describing, you want to dynamically allocate your structures, using either malloc() or a similar function. Dynamically allocated data will remain valid (assuming you do not overwrite it) until you free() the memory, or until your program terminates. Pointers to these areas of memory will remain valid for that same period of time.
Consider:
static struct position *topOfStack = NULL;
void push(struct position *node)
{
node->prev = topOfStack;
topOfStack = node;
}
struct position *pop()
{
struct position *popped = topOfStack;
if (topOfStack) topOfStack = topOfStack->pref;
return popped;
}
To use this, you can:
f() {
struct position *node = malloc(sizeof(*node));
/* ... fill in node details ... */
push(node);
}
Notice that I allocated the node dynamically. Had I just declared a struct position node;, I could legally call push(&node); but once my function left scope, the stack would have an invalid item in it (which would likely cause havoc).
what happens when I try to pass it to function pop?
it depends on your pop() function prototype. If the pop's function prototype should be:
struct position* pop(struct position* stack);
I can create a position object that points to this one and return that, but will it be pushed off the stack when the function closes?
your question is quite unclear, and it looks like a big misunderstanding of instance scoping in C. Basically, you have two ways to allocate variables, either on the stack or on the heap. The scoping you're talking about is stack instances scope.
What if I decide to create several of these nodes in a function? Will they remain once the function closes?
basically, if you use the stack, they will live as long as the scope they're declared in. In C, scope is defined by { and }. for example:
int main() {
struct position pos1;
struct position pos2;
struct position pos3;
pos3.prev = pos2;
pos2.prev = pos1;
pos1.prev = NULL;
pop(&pos3);
}
there you declare 3 variables, and associate them, and the pop function just resets the .prev link. But for a stack that kind of architecture is not really useful, because it is quite limited.
There you definitely need to push your instances in the heap, thus using malloc() and free():
// push() pseudocode:
// take stack, iterate over each prev until prev is NULL
// allocate prev with malloc() the same way as for "stack" in main()
// insert values in prev
void push(struct position* stack, int* value);
// pop() pseudocode:
// take stack, iterate over each prev until prev->prev is NULL,
// then keep prev->prev in a temporary variable
// set prev to NULL
// return temporary variable (former prev->prev)
struct position* pop(struct position* stack);
int main() {
int value[2];
struct position* stack = malloc(sizeof(struct position));
// value is what you want to push to the stack
value[0] = 42;
value[1] = 42;
push(stack, value);
value[0] = 2;
value[1] = 20;
push(stack, value);
struct position* pos;
pos = pop(stack);
// do something with pos->value
free(pos);
}
there you create a pointer to a node for which you allocate some memory in the heap. the push() function is allocating some new memory, assigning .prev for that new space to stack's address and populating that memory with the value. pop() should get to the value before the last one, reset its pointer to that value, and return that value.
Of course, I'm just giving concepts and ideas here, I'm leaving you get to the real implementation. One advice though, instead of using square that contains an array, use two separate values in your struct, that will make it simpler for a first implementation.
In this piece of code I'm trying to create a list which contains all the chars form an input file, and my main problem is with the sentence "You can't return a local variable of the function" Iv'e been told which made me very confused. I dynamically allocated a List and return it, can I just define List list without a dynamic allocation and return it? I believe it's wring since all the information would be automatically deleted and I would be left only with the address of the original list I created.
Here's the code for more information:
typedef struct Item {
char tav;
struct Item* next;
} Item;
typedef struct List {
Item* head;
} List;
List* create(char* path) {
FILE* file;
List* list;
Item* trav;
Item* curr;
char c;
file=fopen(path, "r");
if (file==NULL) {
printf("The file's not found");
assert(0);
}
if (fscanf(file, "%c", &c)!=1) {
printf("The file is empty");
assert(0);
}
trav=(Item *)calloc(1, sizeof(Item));
trav->tav=c;
list=(List *)calloc(1, sizeof(List)); /* allocating dynamiclly the list so it won't be lost at the end of the function*/
list->head=trav;
while (fscanf(file, "%c", &c)==1) {
curr=(Item*)calloc(1, sizeof(Item));
curr->tav=c;
trav->next=curr;
trav=curr;
}
trav->next=NULL;
fclose(file);
return list;
}
Am I correct? Is this necessary? can I define List instead a pointer to one a return it?
You cannot return a pointer to variable local to the function. The local variable does not live beyond the scope({,}) of the function.
Returning address of a variable local to a function will give you what is called as an Undefined Behavior.
You can very well return:
a local variable by value or
a pointer pointing to dynamically allocated memory
Prefer the first unless you are really bothered about the memory overhaed due to returning a copy.
can I just define List list without a dynamic allocation and return it?
Yes,
Provided you have:
List create(char* path);
You can't return a local variable of the function
This sentence is completely wrong. For example in this function:
int f(void)
{
int x = 5;
return x;
}
is a perfectly valid function in which you are returning a local variable.
What you should know is that you can't (or better say shouldn't) return the address of a local variable of the function. This is because after the function returns the address points to garbage and is not usable anymore.
In your example, you can very safely define a local List and return it.
Note that you still need to dynamically allocate trav, i.e. you can't take a local variable of type Item and the point list->head to it for the same reason above.