2010-10-23 4 views
1

Je travaille sur une affectation d'uni, qui doit être faite en C. C'est ma première programmation en C, et je suis TRÈS proche d'avoir une solution réalisable, mais mon code lance une erreur de segmentation pendant l'exécution et je ne parviens tout simplement pas à trouver la cause.Donner un coup de pied à mon cul par une erreur de segmentation

Voici mon code:

#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; 
} 

Quelqu'un peut-il aider s'il vous plaît - je ne veux pas vraiment à l'échec de cette cession (due en moins de 24 heures). Jusqu'à présent, ce n'est pas bon.

MISE À JOUR:

Je suis allé et a ajouté un bucketload de ce fprintf dans tous les sens, et après un certain temps, je pense j'ai isolé le problème sur cette ligne:

if (best_proc->f_link != NULL) { 

I Je ne sais pas comment cela m'aide, mais dans le vain espoir que cela aide quelqu'un à voir le problème (parce que je ne sais pas), alors tant mieux. De plus, pour être clair, je ne crois pas que ce soit une application multithread (bien que je sois un noob complet, donc qui sait vraiment) - et je ne savais pas que je pouvais avoir un débogueur ou un stack-trace (travaillant à partir de la 1ère édition K & R "Le langage de programmation C") donc je ne les ai pas non plus. (D'un autre côté, la programmation en C ressemble-t-elle normalement à un gros japonais qui vous frappe au visage?)

+1

Est-ce que votre débogueur ou de l'éditeur vous dire où l'segfault se produit? – BoltClock

+1

S'il vous plaît donnez-nous la trace de la pile – Woot4Moo

+0

@ Woot4Moo: C'est juste un tas de commentaires: P – BoltClock

Répondre

3

Cela me va bien - ne trouve aucune erreur dans le code.

Échec immédiatement, ou après avoir fonctionné un peu? Êtes-vous sûr que la fonction init_q s'exécute réellement avant de commencer à utiliser la file d'attente? Avez-vous essayé de vérifier si vous obtenez NULL en tant que paramètre aux fonctions new_insert ou re_insert? Par ailleurs, ce programme ne fonctionne pas en mode multithread, n'est-ce pas? Si c'est le cas, vous devez protéger vos variables globales dans les sections critiques.

EDIT4: MAINTENANT, je pense que je l'ai eu! ready_q_tail n'est jamais définie à une nouvelle valeur lors de la suppression de la dernière tâche de la file d'attente.

est ici un schedule_next fixe (je l'espère) la fonction:

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

Désolé, pas de joie, j'ai peur. – Ash

+0

@Ash: D'accord, répondez à nouveau mis à jour. Et si ma fonction ne fonctionne pas, j'ai fait une erreur quelque part. Mais la clé est que 'ready_q_tail' n'a jamais été rejoint à la nouvelle queue lors de la suppression de la dernière tâche dans la file d'attente. C'est probablement la cause de votre faute de segmentation. – gablin

+0

Holy cow, vous l'avez fait! Merci merci merci. Maintenant, j'ai juste besoin de diagnostiquer les différences. – Ash

0

Utilisez valgrind pour trouver des bugs mémoire. Parfois, une fausse manipulation de la mémoire commence bien avant que vous obteniez une erreur de segmentation.

+0

J'ai clarifié la question certains. – Ash