Home > Software engineering >  C linked list input memory not carrying over (Maybe)
C linked list input memory not carrying over (Maybe)

Time:05-31

I am quite inexperienced at coding so I am not sure what is going on, but I have run my code through godbolt compiler/debugger, and it says that there is a memory leak but I don't know how to solve this problem I do believe the issue is within the void end function though.

GodBolt Link

#include <iostream>
#include <stdio.h>
using namespace std;

class node {
public:
    int value = 0;
    string month;
    node* next;
};

struct NewValues {
    long int a = 0, b = 0, c = 0, d = 0, e = 0, f = 0;
} n;

//function moves newvalues infront of linked list
void AtFront(node** head)
{
    node* Dec = new node();
    Dec->value = n.c;
    Dec->month = "December 2021: $";
    Dec->next = *head;
    *head = Dec;

    node* Nov = new node();
    Nov->value = n.b;
    Nov->month = "November 2021: $";
    Nov->next = *head;
    *head = Nov;

    node* Oct = new node();
    Oct->value = n.a;
    Oct->month = "October 2021: $";
    Oct->next = *head;
    *head = Oct;
}

//puts new values at the end of the linked list
void End(node** head)
{
    node* June = new node();
    June->value = n.d;
    June->month = "June 2022: $";
    June->next = NULL;

    //if linked list is empty, newnode will be a head node
    if (*head == NULL) {
        *head = June;
        return;
    }

    //find the last node
    node* last = *head;
    while (last->next != NULL) {
        last = last->next;
    }

    last->next = June;

    node* July = new node();
    July->value = n.e;
    July->month = "July 2022: $";
    July->next = NULL;
    last->next = July;

    node* Aug = new node();
    Aug->value = n.f;
    Aug->month = "August 2022: $";
    Aug->next = NULL;
    last->next = Aug;
}

void sumOfNodes(node* head, long int* sum)
{
    // if head = NULL
    if (!head)
        return;

    // recursively traverse the remaining nodes
    sumOfNodes(head->next, sum);

    // accumulate sum
    *sum = *sum   head->value;
}

int sumOfNodesUtil(node* head)
{
    long int sum = 0;

    // find the sum of  nodes
    sumOfNodes(head, &sum);

    // required sum
    return sum;
}

void printList(node* n)
{
    cout << "\nList of earnings from October 2021 - August 2022\n" << endl;
    while (n != NULL) {
        cout << n->month << n->value << endl;
        n = n->next;
    }
}

int main()
{
    node* head = new node();
    node* second = new node();
    node* third = new node();
    node* fourth = new node();
    node* fifth = new node();

    cout << "There are a total of 6 months unaccounted for.." << endl;
    cout << "please enter in the data for the month when prompted" << endl;

    cout << "\nOctober 2021: $";
    cin >> n.a;

    cout << "November 2021: $";
    cin >> n.b;

    cout << "December 2021: $";
    cin >> n.c;

    cout << "June 2022: $";
    cin >> n.d;

    cout << "July 2022: $";
    cin >> n.e;

    cout << "August 2022: $";
    cin >> n.f;

    head->value = 500;
    head->month = "January 2022: $";
    head->next = second;

    second->value = 125;
    second->month = "Febuary 2022: $";
    second->next = third;

    third->value = 200;
    third->month = "March 2022: $";
    third->next = fourth;

    fourth->value = 300;
    fourth->month = "April 2022: $";
    fourth->next = fifth;

    fifth->value = 600;
    fifth->month = "May 2022: $";
    fifth->next = NULL;

    AtFront(&head);
    End(&head);
    printList(head);

    long int avg = sumOfNodesUtil(head) / 11;

    cout << "\nTotal earnings: $" << sumOfNodesUtil(head) << endl;
    cout << "Average: $" << avg << endl;
}

CodePudding user response:

For every use of new to dynamically allocate memory, you must also use delete to deallocate that memory. You have used new but not delete so you have a memory leak.

When dealing with a linked list, each node links to the next. The trick is that if you delete a node, you've deleted the pointer to the rest of the list, but not the data it points to.

Consider a very basic linked list. (The principle transfers.)

I'm going to give it a constructor for ease of use.

struct Node {
    int val;
    Node *next;

    Node(int v, Node *n=nullptr) : val(v), next(n) { }
};

We can allocate a new node:

Node *head = new Node(42);

And a list with a few items:

Node *head = new Node(42);
head->next = new Node(27);
head->next->next = new Node(13);

Now, if I delete head; I haven't actually deleted the next two nodes. Rather I've destroyed anyway of getting to those to delete them, guaranteeing I'll leak memory.

We can iterate over the list and delete as we go, using temp pointers so we don't lose track of the rest of the list.

Node *head = new Node(42);
head->next = new Node(27);
head->next->next = new Node(13);

Node *temp = head;
while (temp) {
    Node * temp2 = temp->next;
    delete temp;
    temp = temp2;
}

We can integrate this functionality into a destructor.

struct Node {
    int val;
    Node *next;

    Node(int v, Node *n=nullptr) : val(v), next(n) { }

    ~Node() {
        Node *temp = next;
        while (temp) {
            Node *temp2 = temp->next;
            delete temp;
            temp = temp2;
        }
    }
};

With the destructor, the list will clean itself up automatically when going out of scope if it's been automically allocated; or if it's been dynamically allocated with new, we need only delete the head:

Node *head = new Node(42);
head->next = new Node(27);
head->next->next = new Node(13);

delete head;
  • Related