Search code examples
c++linked-listround-robin

Code in involving round robin scheduling fails to run or gives a segmentation fault(core dumped)


(C++) My code is supposed to mimic the round robin cpu scheduling algorithm using linked lists (so accept list of process names with times ex: ProcessA 10, subtract 3 from the times, if the result is greater than 0 it is shifted to end of list. This continues until process time reaches 0 where at that point the process is finished).

My program accepts and displays the list of processes and their times correctly. So I didn't include the code for accepting, creating, and displaying the list. Somewhere after displaying the list the user has inputted, the program just abruptly ends for some reason.

my output:

[John@fish lab2]$ ./a.out
Enter your processes, to end press '^d'
ProcessA 4
Enter your processes, to end press '^d'
ProcessB 10
Enter your processes, to end press '^d'
ProcessC 6
Enter your processes, to end press '^d'
^d
Displaying the list of processes:
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
ProcessA 4
ProcessB 10
ProcessC 6
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^


I tried modifying the while loop since I thought there was an issue with the flag so I changed it from while(print_flag) to while(true) and placed a break statement in the else condition.

my output:

same as last ouput except with an extra line saying : 'segmentation fault(core dumped)'

I have no idea on how to fix the underlying issue. Any help is appreciated.

#include <iostream>
#include <list>
#include <stdio.h>
#include <unistd.h>
#include <signal.h>
#include <string>

using namespace std;

volatile sig_atomic_t print_flag = false;

struct NodeType
{
    string value1; //process name
    int value2; //process time
    NodeType* next;
    
    void DisplayLinkedList(NodeType* head)
    {
        NodeType* p;

        p = head;   //initialize pointer p to point to the first node in the linked list 

        cout << "Displaying the list of processes: " << endl;
        cout << "^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^" << endl;
        while (p != NULL)
        {
            cout << p->value1 << " " << p->value2 << endl;
            p = p->next;  //update p to point to next node in the linked list ... 
        }
        cout << "^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^" << endl;
        cout << " " << endl;
    }

    void createnode(NodeType*& head, string x, int y)
    {
        NodeType* p = new NodeType;
        
        
        if (head == NULL)
        {
            p->value1 = x;
            p->value2 = y;
            p->next = NULL;
            head = p;
        }
        else
        {
            p = head;
            while (p->next != NULL)
                p = p->next;
            p->next = new NodeType;
            p = p->next;
            p->value1 = x;
            p->value2 = y;
            p->next = NULL;
            
        }
    }

    bool IsEmpty(NodeType* h) const
    {
        return h == NULL;
    }

    void DeleteNode(NodeType*& head)
    {
        NodeType* p = head;
        head = head->next;
        delete p;
    }

    
    void roundrobin(NodeType*& head)
    {
        head->value2 -= 3;
        if (head->value2 == 0) // no time remaining 
        {
            cout << head->value1 << " Finished" << endl;
            DeleteNode(head);
        }
        else // time remaining
        {
            NodeType* p = head;
            p->next = NULL;
            head = head->next;
            NodeType* q = head;
            while (q->next != NULL)
                q = q->next;
            q->next = p;
        }
    }
};

void handle_alarm(int sig) // interrupt handler, manipulates flags to allow roundrobin to run
{
    print_flag = true;
}


int main()
{
    NodeType* head = NULL;
    NodeType a;
    string v, x, y;
    int argc = 0;
    int z = 0;
    

    while(true)
    {
        cout << "Enter your processes, to end press '^d' " << endl;
        getline(cin, v);
        if (v == "^d")
            break;
        //cin >> a;
        int index = v.find(" "); 
        x = v.substr(0, index); 
        y = v.substr(index + 1, v.length());
        
        z = stoi(y);
        a.createnode(head, x, z);

        argc++;
    }

    a.DisplayLinkedList(head);
    
    signal(SIGALRM, handle_alarm);
    alarm(3);
    while (print_flag)
    {
        
            if (a.IsEmpty(head) == false) // list not empty
            {
                a.roundrobin(head);
                a.DisplayLinkedList(head);
            }
            else
            {
                cout << "No more processes left" << endl;
                print_flag = false;
            }
        
        //print_flag = false;
        alarm(3);
    }
    
    return 0;
}


Solution

  • I think you need to make some small changes in your roundrobin function for it to work:

    You need to update the condition to check if a process is finished to head->value2 <= 0 instead of head->value2 == 0 since head->value2 == 0 seems only to work for any process with value2 is divisible by 3 and it will miss other processes as they will be minus down to negative numbers through this expression head->value2 -= 3

    You also need to bring your p->next = NULL; line after head = head->next; instead of before. Otherwise, head will always be NULL as p is currently head.

    Finally, you need to check for if head is the only process left (head->next != NULL) before switching to the next process. Otherwise, you would make your head becomes NULL if head->next is NULL, causing segmentation fault error

      void roundrobin(NodeType*& head)
      {
        head->value2 -= 3;
        if (head->value2 <= 0) // no time remaining 
        {
          cout << head->value1 << " Finished" << endl;
          DeleteNode(head);
        }
        else // time remaining
        {
          NodeType* p = head;
          if (head->next != NULL) {
            head = head->next;
            p->next = NULL;
            NodeType* q = head;
            while (q->next != NULL)
              q = q->next;
            q->next = p;
          } 
        }
      }