Infinite loop iterating over a linked list

AI Thread Summary
The discussion centers on a coding issue involving an infinite loop when iterating over a linked list in C. The primary problem identified is in the `IntListCons` function, where a local variable is returned, leading to undefined behavior after the function exits. The solution proposed involves using dynamic memory allocation with `malloc` to ensure the linked list nodes persist beyond the function's scope. Additionally, participants emphasize the importance of freeing allocated memory to avoid memory leaks. Proper coding practices, such as using code tags for readability and naming conventions for pointer types, are also discussed.
TheMathNoob
Messages
189
Reaction score
4
Mod note: Added code tags
1. Homework Statement

in my main I am getting infinite loop iterating over a link list

Homework Equations

The Attempt at a Solution


C:
/*
* graph.c
*
*  Created on: Oct 8, 2015
*      Author: danif
*/
#include <stdio.h>
#include "IntList.h"

int main(void)
{

    typedef struct IntListStruct* List;
    List l1=IntListCons(3,NULL);
    List l2=IntListCons(3,l1);
    List l3=IntListCons(4,l2);
    List Tester;

    Tester=l3;
    while(Tester!=NULL)
    {
        printf("%d\n",Tester->element);
        Tester=rest(Tester);
    }}/*
* IntList.c
*
*  Created on: Oct 8, 2015
*      Author: danif
*/
#include "IntList.h"struct IntListStruct* IntListCons(int newb, struct IntListStruct *oldList)
{
    struct IntListStruct newL;
    newL.element=newb;
    newL.pt=oldList;
    struct IntListStruct* pnewL= &newL;

    return pnewL;
}

int first(struct IntListStruct* L)
{

    return L->element;
}

struct IntListStruct* rest(struct IntListStruct* L)
{
    return L->pt;
}
 
Last edited by a moderator:
Physics news on Phys.org
in the future please put all code inside ['code']['/code'] (without the '). Makes it easier to read.Also what is the problem you are having? What do you believe the program should do?
 
cpscdave said:
in the future please put all code inside ['code']['/code'] (without the '). Makes it easier to read.Also what is the problem you are having? What do you believe the program should do?
I previously stated that the problem is an infinite loop, so how can I fix that?. I am just trying to display every element in the list.
 
TheMathNoob said:
I previously stated that the problem is an infinite loop, so how can I fix that?. I am just trying to display every element in the list.
Are you using a debugger?

Also, please show us your header file, IntList.h.
 
Mark44 said:
Are you using a debugger?

Also, please show us your header file, IntList.h.
/*
* IntList.h
*
* Created on: Oct 8, 2015
* Author: danif
*/

#ifndef INTLIST_H_
#define INTLIST_H_
#include <stdio.h>
typedef struct IntListStruct* IntList;
struct IntListStruct* rest(struct IntListStruct *L);
struct IntListStruct* IntListCons(int newb, struct IntListStruct *oldList);
int first(struct IntListStruct* L);

struct IntListStruct
{
IntList pt;
int element;

};#endif /* INTLIST_H_ */
 
Mark44 said:
Are you using a debugger?

Also, please show us your header file, IntList.h.
I forgot to replace InList with struct IntListStruct* in some of the prototypes, but that should be a minor point
 
TheMathNoob said:
/*
* IntList.h
*
* Created on: Oct 8, 2015
* Author: danif
*/

#ifndef INTLIST_H_
#define INTLIST_H_
#include <stdio.h>
typedef struct IntListStruct* IntList;
struct IntListStruct* rest(struct IntListStruct *L);
struct IntListStruct* IntListCons(int newb, struct IntListStruct *oldList);
int first(struct IntListStruct* L);

struct IntListStruct
{
IntList pt;
int element;

};#endif /* INTLIST_H_ */
Please use code tags -- [ code ] at the top and [ /code ] at the bottom (no extra spaces). They make your code more readable.
 
Mark44 said:
Please use code tags -- [ code ] at the top and [ /code ] at the bottom (no extra spaces). They make your code more readable.
Thank you for the the advice. I will keep it in mind.
 
I believe there is a bug in your IntListCons() function.
C:
struct IntListStruct* IntListCons(int newb, struct IntListStruct *oldList)
{
    struct IntListStruct newL;
    newL.element=newb;
    newL.pt=oldList;
    struct IntListStruct* pnewL= &newL;

    return pnewL;
}
The newL struct is a local that is allocated on the stack when this function is entered, and "dies off" when control returns to the caller. The pointer you're returning is the address of memory that is subject to change.
 
  • #10
Mark44 said:
I believe there is a bug in your IntListCons() function.
C:
struct IntListStruct* IntListCons(int newb, struct IntListStruct *oldList)
{
    struct IntListStruct newL;
    newL.element=newb;
    newL.pt=oldList;
    struct IntListStruct* pnewL= &newL;

    return pnewL;
}
The newL struct is a local that is allocated on the stack when this function is entered, and "dies off" when control returns to the caller. The pointer you're returning is the address of memory that is subject to change.
Ok, so how can I create an struct that doesn't die once the control returns to the caller. I think that there is an explanation behind about extern and all of that types. Or I think that I have dynamic memory
 
  • #11
TheMathNoob said:
Ok, so how can I create an struct that doesn't die once the control returns to the caller. I think that there is an explanation behind about extern and all of that types. Or I think that I have dynamic memory
You can allocate memory dynamically on the heap (instead of the stack) using malloc() -- its prototype is in stdlib.h.
 
  • Like
Likes cpscdave
  • #12
Mark44 said:
I believe there is a bug in your IntListCons() function.
C:
struct IntListStruct* IntListCons(int newb, struct IntListStruct *oldList)
{
    struct IntListStruct newL;
    newL.element=newb;
    newL.pt=oldList;
    struct IntListStruct* pnewL= &newL;
    return pnewL;
}
The newL struct is a local that is allocated on the stack when this function is entered, and "dies off" when control returns to the caller. The pointer you're returning is the address of memory that is subject to change.
I

The solution to the problem is this

IntList IntListCons(int newb, struct IntListStruct *oldList)
{
IntList pnewL= malloc(sizeof(struct IntListStruct));
pnewL->element=newb;
pnewL->pt=oldList;

return pnewL;
}

can you explain more about dynamic memoey and stack memory?. Explain me how this code really works.
 
  • #13
TheMathNoob said:
I

The solution to the problem is this

IntList IntListCons(int newb, struct IntListStruct *oldList)
{
IntList pnewL= malloc(sizeof(struct IntListStruct));
pnewL->element=newb;
pnewL->pt=oldList;

return pnewL;
}

can you explain more about dynamic memoey and stack memory?. Explain me how this code really works.
PLEASE USE CODE TAGS!
 
  • Like
Likes cpscdave
  • #14
Without getting too technical about how the stack operates.
When you create a variable inside of a function. The compiler assumes that the memory it allocates for it is only need so long as you haven't exited from the function. When it does exit from the function the compiler returns the memory to the computer and forgets about it.
What generally does happen is that memory is used for something else and you've lost whatever you placed there.

When you use malloc the compiler takes memory from somewhere else, and reserves it till the memory is freed using the free command.
PROTIP everytime you add a malloc to a program you should immediately add a corresponding free and code to ensure all malloc'd memory is free'd. Good programming habit to get into early.
 
  • #15
cpscdave said:
Without getting too technical about how the stack operates.
When you create a variable inside of a function. The compiler assumes that the memory it allocates for it is only need so long as you haven't exited from the function. When it does exit from the function the compiler returns the memory to the computer and forgets about it.
What generally does happen is that memory is used for something else and you've lost whatever you placed there.

When you use malloc the compiler takes memory from somewhere else, and reserves it till the memory is freed using the free command.
PROTIP everytime you add a malloc to a program you should immediately add a corresponding free and code to ensure all malloc'd memory is free'd. Good programming habit to get into early.
So the code to release memory would look something like this

IntList releaser=Tester;
while(Tester!=NULL)
{
Tester=rest(Tester);
free(releaser);
releaser=Tester;
}
 
Last edited:
  • #16
Mark44 said:
PLEASE USE CODE TAGS!
 
  • #17
I'm sure several of us have comments about you last code. Speaking for myself, if you can't be convinced to make your code "pretty" with code tags, I don't feel like spending the time helping out.

PLEASE USE CODE TAGS!
 
  • #18
This would be a bit less code:

Code:
IntList releaser;
    while(Tester!=NULL)
    {
        releaser=Tester;
        Tester=rest(Tester);
        free(releaser);
    }

If you're going to use typedefs for pointer types, you might want to consider prefixing them with a P if it's not obvious, like PNode for pointer to node, or just use Node * for pointer assuming that Node is a typedef for a struct.
 
Last edited:

Similar threads

Replies
5
Views
2K
Back
Top