Получение моей задницы, измученной ошибкой сегментации - PullRequest
1 голос
/ 23 октября 2010

Я работаю над уникальным заданием, которое должно быть выполнено на C. Это мое первое программирование на C, и я ОЧЕНЬ близок к выполнению работоспособного решения, но мой код выдает ошибку сегментации во время выполнения иЯ просто не могу найти причину.

Вот мой код:

#include "./shared.h"
#include "./scheduler.h"

PCB_entry      *ready_q ;
PCB_entry      *ready_q_tail;

/*
 * file name priority.c
 *
 * The functions in this file implement a "priority"
 * scheduling scheme. 
 *
 * Functions provided and brief descriptions:
 *
 * PCB_entry * schedule_next (void) - returns next process for CPU
 * 
 * int insert_new (PCB_entry * proc) - insert new process into queue
 *
 * void list_q (void) - debugging function lists queue contents
 *
 * int re_insert (PCB_entry * proc, int run_time) - put process back
 *                 into correct queue after a run on the CPU 
 *
 * int init_q (void) - initialise queue(s)
 *
 */


double pwr (double x, double y)
{
    double i, p;
    p = 1;
    for (i = 1; i <= y; ++i){
        p = p * x;
    }
    return p;
}


/*
 * Function Schedule_next: priority
 * 
 * Called by the central simulation system Returns a 
 * pointer to the PCB entry for the "process" that 
 * should be put on the CPU next
 * 
 */
PCB_entry *
schedule_next (void)
{
   /* if ready_q is null, there are no processes in the system */
   if (ready_q == NULL)
     {
    return NULL;
     }
   else
     { 
       PCB_entry *next;
       PCB_entry *best_proc;

        next = ready_q;
        best_proc = next;
           while (next != NULL)
             {              /* traverse to the end of the list */

            if (next->current_priority < best_proc->current_priority) {
                best_proc = next;   
            }
            next = next->f_link;
           }
        if (best_proc == NULL) {
            return NULL;
        }

        if (best_proc->b_link != NULL){
            best_proc->b_link->f_link = best_proc->f_link;
            if (best_proc->f_link != NULL) {
                best_proc->f_link->b_link = best_proc->b_link;
            }
        } else {

            ready_q = best_proc->f_link;


            if (ready_q != NULL)    /* don't try to de-reference a NULL
                                     * pointer */
               ready_q->b_link = NULL;  /* first process in the queue
                                         * always has a NULL back
                                         * link */
            best_proc->f_link = NULL;   /* just to be tidy -- set both links
                         * in the PCB */
            /* entry that will be returned to NULL */
            best_proc->b_link = NULL;
        }

        return best_proc;

    }
}

/*
 * Function insert_new: Non-preemptive round-robin
 * 
 * Insert a new "process" into the scheduling queue
 * 
 * Accepts a pointer to a PCB entry that will be inserted
 * into the queue returns either OK or NotOK to indicate 
 * success or failure
 * 
 * Since this is FCFS priority scheduling, the new process is
 * simply slotted in at the end of the queue
 * 
 */
int
insert_new (PCB_entry * proc)
{

   if (ready_q == NULL)
     {              /* no entries in table */
    ready_q = proc;     /* insert at the head of the list */
    proc->b_link = NULL;
    proc->f_link = NULL;
    ready_q_tail = ready_q;
    return OK;
     }
   else
     {

        ready_q_tail->f_link = proc; /* Set tail of list pointer */
        proc->f_link = NULL;         /* New tail of list to NULL */
        proc->b_link = ready_q_tail; /* Set the b_link of the new process to previous last record of the list */
        ready_q_tail = proc;         /* Set the tail reference to the new pointer */
    return OK;
     }
#pragma error_messages (off,E_STATEMENT_NOT_REACHED)
   return NotOK; /* this is not really needed, but is here to be defensive */
#pragma error_messages (on,E_STATEMENT_NOT_REACHED)
}

/*
 * Function list_q
 * 
 * Implementation of this function is optional but highly 
 * recommended
 */

void
list_q (void)
{
   PCB_entry *next;

   next = ready_q;

   fprintf (stderr, "\n current state of the ready queue\n");

   next = ready_q;
   while (next != NULL)
     {              /* traverse to the end of the list */
    fprintf (stderr, "%d\t", next->pid);
    next = next->f_link;
     }
   fprintf (stderr, "\n\n");
}


/*
 * Function re_insert: priority
 * 
 * a function to insert a process back into the queue
 * following a run on the CPU. Depending on the
 * scheduling algorithm chosen this would need to
 * do a lot more. In a priority algorithm with boost
 * and reduction, it would need to look at the
 * percentage of the quantum that the process used
 * and determine if a change to the priority was
 * required. Also, in implementing a mulitlevel
 * priority scheme, a variation of the ready_q
 * pointer would be required. The simplest method
 * would be an array of pointers with one element
 * for each priority level.
 *
 * Not that, in this case it is identical to the
 * insert_new code
 */
int
re_insert (PCB_entry * proc, int run_time)
{
    insert_new(proc);
}


/*
 * Function init_q: FCFS priority
 * 
 * Initialises the ready queue
 * 
 * Written as a function so that, if the ready_q
 * becomes an array of pointers, the initialisation
 * can be changed without re-building the main part
 * of the simulator
 */

int
init_q (void)
{
   ready_q = NULL;
    ready_q_tail = NULL;    
   return OK;
}



/*
 * function end_run () 
 * Insert code to do any end of processing tasks for the
 * functions written by the student
 */
int end_run(void)
{
   fprintf(stderr, "This run had %d concurrent processes\n", Get_num_concurrent());
   return 0;
}

Может кто-нибудь, пожалуйста, помогите - я действительно не хочу проваливать это назначение (менее чем за 24 часа).Пока что это выглядит не очень хорошо.

ОБНОВЛЕНИЕ:

Я пошел и добавил кучу fprintf повсюду, и через некоторое время я думаю IВыделили проблему в этой строке:

if (best_proc->f_link != NULL) {

Я не знаю, как это помогает мне, но напрасно надеюсь, что это поможет кому-то увидеть проблему (потому что я уверен, что нет), тогда тем лучше.

Кроме того, для ясности, я не верю, что это многопоточное приложение (хотя я полный нуб, так что кто действительно знает) - и я не знал, что я мог бы иметь отладчик или стек.trace (работает с 1-го издания K & R "The C Programming Language"), поэтому у меня его тоже нет.(Следует отметить, что программирование на C обычно ощущается так, будто толстый японец бьет тебя по лицу?)

Ответы [ 2 ]

3 голосов
/ 23 октября 2010

Для меня все в порядке - не могу найти никаких ошибок в коде.

Не получается сразу или после небольшого пробега? Вы уверены, что функция init_q действительно запускается перед началом использования очереди? Вы пытались проверить, получаете ли вы NULL в качестве параметра для new_insert или re_insert функций?

Кстати, эта программа не работает в многопоточном режиме, верно? Если это так, вам нужно защитить свои глобальные переменные в критических разделах.

EDIT4: СЕЙЧАС, я думаю, я понял! ready_q_tail никогда не устанавливается в новое значение при удалении последней задачи из очереди.

Вот (надеюсь) исправленная schedule_next функция:

PCB_entry *
schedule_next (void)
{
   /* if ready_q is null, there are no processes in the system */
   if (ready_q == NULL)
     {
    return NULL;
     }
   else
     { 
       PCB_entry *next;
       PCB_entry *best_proc;

        next = ready_q;
        best_proc = next;
           while (next != NULL)
             {              /* traverse to the end of the list */

            if (next->current_priority current_priority) {
                best_proc = next;   
            }
            next = next->f_link;
           }
        if (best_proc == NULL) {
            return NULL;
        }

        // Remove task from queue
        {
            int procHasNext = best_proc->f_link != NULL;
            int procHasPrev = best_proc->b_link != NULL;

            if (!procHasNext && !procHasPrev) {
                // There's only one task in the queue
                ready_q = NULL;
                ready_q_tail = NULL;
            } else {
                if (procHasNext) {
                    if (procHasPrev) {
                        best_proc->b_link->f_link = best_proc->f_link;
                    } else {
                        // Proc to remove is the first in queue
                        ready_q = best_proc->f_link;
                        ready_q->b_link = NULL;
                    }
                }

                if (procHasPrev) {
                    if (procHasNext) {
                        best_proc->f_link->b_link = best_proc->b_link;
                    } else {
                        // Proc to remove is last in queue
                        ready_q_tail = best_proc->b_link;
                        ready_q_tail->f_link = NULL;
                    }
                }
            }
        }

        // Ensure that the links in PCB to remove doesn't cause any problems
        best_proc->f_link = NULL;
        best_proc->b_link = NULL;

        return best_proc;

    }
}
0 голосов
/ 23 октября 2010

Используйте valgrind, чтобы найти ошибки памяти.Иногда ложное обращение с памятью начинается задолго до того, как вы на самом деле получите ошибку.

...