[C] vreemde segfault bij if statement

Pagina: 1
Acties:

  • Elephtera
  • Registratie: Juni 2001
  • Laatst online: 15:29
Ik moet voor de uni een lift simulatie maken, en hierbij ben ik nu op een vervelende segfault gekomen.

ik heb de fout terug kunnen lijden tot een if statement.

hieronder de code van de betreffende functie:
C:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
static T_passenger passenger;
T_passenger *pickup_passenger(T_elevator *el)
{
  /*T_passenger *passenger;
  passenger = malloc(sizeof(T_passenger));
  if (passenger == NULL){
    printf("malloc error\n");
    exit(1);
  } */
  printf("pickup passenger...\n");
  int i;
  /* first check idle state */
  printf("state = %d",(*el).state);
  int j = (*el).state;
  printf(". or %d\n", j);
  if (j != 0){
    printf("elevator!=IDLE ");
    for(i = 0; i < MAX_PASSENGERS; i++){
      if ((*pqueue[(*el).location].waiting[i]).direction == (*el).state){
        printf("Same direction...");
        passenger = (*pqueue[(*el).location].waiting[i]);
        pqueue[(*el).location].waiting[i] = 0;
        pqueue[(*el).location].total--;
        if((*el).state == MOVING_UP) {pqueue[(*el).location].up--;}
        if((*el).state == MOVING_DOWN) {pqueue[(*el).location].down--;}
        printf("Completed\n");
        return &passenger;
      } 
    }
  }
  else{
    printf("elevator==IDLE ");
   
    for(i = 0; i < MAX_PASSENGERS; i++){
      if (pqueue[(*el).location].waiting[i] != 0){
     
        passenger = (*pqueue[(*el).location].waiting[i]);
        pqueue[(*el).location].waiting[i] = 0;
        pqueue[(*el).location].total--;
        if(passenger.direction == PASSENGER_UP) {pqueue[(*el).location].up--;}
        if(passenger.direction == PASSENGER_DOWN) {pqueue[(*el).location].down--;}
        (*el).state = passenger.direction;
        printf("Completed\n");
        return &passenger;
      }
    }

  }


printf("no waiting people");
exit(1);
}


hij doorloopt de code meerdere malen, echter bij de tweede run geeft hij bij de if(j!=0) in regel 16 een segmentation fault.
de eerste maal is j nog 0, en dan gaat hij naar de else, (elevator=idle)
2e maal issie op 2 ingesteld (going down) maar dan krijg ik dus een seg fault, eerst had ik het if statement met de (*el).state, maar vanwege de segfault toen in een int gestopt, die geeft echter dezelfde fout bij het if statement. het printen met printf werkt wel gewoon.

type defs in de bijbehorende header files:
C:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
typedef struct T_passenger {
  int floor; 
  int dest;
  int direction;
  /*
   * Needed: current floor, destination floor and 
   * Direction based on floor and dest.
   */
} T_passenger;

typedef struct T_elevator {
  int state;
  int door;
  int location;
  int nr_passengers;
  int req_floors[NR_OF_FLOORS];
  struct T_passenger *passengers[ELEVATOR_CAPACITY];
} T_elevator;

[ Voor 4% gewijzigd door Elephtera op 08-03-2006 11:19 ]

“An elephant is a mouse with an operating system”


  • VyperX
  • Registratie: Juni 2001
  • Laatst online: 16-02 16:12
Euhm.... printf-jes zijn niet de meest betrouwbare manier om te debuggen. Dit komt omdat de output niet perse geflushed hoeft te worden naar de output. I.e. als je een printf doet, dan kan deze eerst in een buffer terecht komen, voordat deze echt als output op het scherm komt. Terwijl je text nog in de buffer staat kan de segfault al optreden.

Welke IDE gebruik je voor het maken? Als je een IDE gebruikt zit daar vrijwel altijd een debugger in, die je kan helpen de fout te localiseren.

Nog even inhoudelijk... Waar definieer je de "pqueue" array?

En nog even over de syntax: in plaats van "(*el).state" kan je ook "el->state" gebruiken. Dit leest wat makkelijker.

My Dwarf Fortress ASCII Reward: ~~@~~####,.".D",.B""


  • Elephtera
  • Registratie: Juni 2001
  • Laatst online: 15:29
ik gebruik geen ide, alles in gedit. heb wel een ide geprobeerd, (kdevelop C/C++) maar hier kon ik nog niet vinden hoe een .o file aan te koppelen.
de main.o is namelijk al gecompileerd (eind versie) we moeten de main.c nog zelf maken.

pqueue word als volgt gemaakt:
C:
1
2
3
4
5
6
7
8
9
10
11
typedef struct T_pqueue {
  int up;
  int down;
  int total;
  struct T_passenger *waiting[MAX_PASSENGERS];
  /*
   * Must contain: # up, # down, total #, array[MAX_PASSENGERS] with 
   * pointer to *T_passenger
   * fill in
   */
} T_pqueue;

C:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
static T_pqueue pqueue[NR_OF_FLOORS];

/*
 * Initialize the passenger queues
 */
void
init_pqueue(void)
{
  int i;
printf("init queue\n");
  for (i = 0; i <= NR_OF_FLOORS; i++){
    pqueue[i].up = 0;
    pqueue[i].down = 0;
    pqueue[i].total = 0;
  }
}


en ik heb printf vooral gebruikt om de locatie van de bug te vinden. welke uitvoer is er wel en welke niet, en tussenliggende bezit dus een bug.

ik gebruik (*el).state omdat op sommige plaatsen ook iets als elevator.state word gebruikt, en daar kan volgens mij geen elevator->state
dan houd ik overzicht voor mezelf.

“An elephant is a mouse with an operating system”


  • VyperX
  • Registratie: Juni 2001
  • Laatst online: 16-02 16:12
Zoals ik al zei: printf-jes zijn niet de handigste manier van debuggen. (Vanwege het buffering verhaal.)
Er zijn (dacht ik) twee manieren om ervoor te zorgen dat de buffer wordt weggeschreven voordat er volgende code wordt uitgevoerd.

1. Zet bij elke printf een "\n" achter je text.
2. Roep na elke printf de functie "fflush(stdout)" aan. Deze zorgt ervoor dat je (output) buffer wordt leeggemaakt.

Verder zie ik niet dat je bij je init_pqueue de T_Passengers alloceert die in je pqueue.waiting[] zouden moeten staan.
(Zoals je het nu hebt gedefinieerd, bevat een pqueue struct een array (genaamd waiting) van pointers naar T_Passengers. Deze worden dus niet gealloceerd.)

Hierdoor kan je geen waardes wegschrijven naar die passenger. Dat dit bij de eerste aanroep goed gaat is "puur geluk"... Plus het feit dat je daar alleen een keer 0 wegschrijft.

Een tweede punt is dat je "(pqueue[(*el).location].waiting[i])" (wat een T_Passenger pointer zou moeten zijn) gelijk kan zijn aan null. In dit geval kan je natuurlijk niet de direction van zo'n passenger opvragen.

[ Voor 14% gewijzigd door VyperX op 08-03-2006 12:24 ]

My Dwarf Fortress ASCII Reward: ~~@~~####,.".D",.B""


  • Elephtera
  • Registratie: Juni 2001
  • Laatst online: 15:29
Dankje voor de tips.
zonder printf heb ik dezelfde fout, die hoeven dus niet geleegd te worden, toch?

de pointers naar T_passengers worden gealloceerd in een queue_passengers functie.
de queue moet leeg geinitialiseerd worden, de passengers worden door de main.c gemaakt en toegevoegd. deze worden vervolgens door het programma in een queue gezet.

C:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
int
queue_passenger(T_passenger *p)
{
 printf("queue passenger\n");
  if (pqueue[(*p).floor].total == MAX_PASSENGERS){
    return 0;
  }
  if ((*p).direction == PASSENGER_UP){
    pqueue[(*p).floor].up++;
  }
  else{
    pqueue[(*p).floor].down++;
  }
  pqueue[(*p).floor].total++;
  pqueue[(*p).floor].waiting[pqueue[(*p).floor].total] = &(*p);
  return 1;
}


verder zit de fout in het (*el).state ding.
state = idle/up/down (0/1/2)

“An elephant is a mouse with an operating system”


  • NMe
  • Registratie: Februari 2004
  • Laatst online: 11-03 14:33

NMe

Quia Ego Sic Dico.

offtopic:
Even los van je probleem, maar waarom derefereer je zoveel? (*pointer).nogwat is hetzelfde als pointer->nogwat, en dat tik een stukje makkelijker. En waarom je op regel 15 van je laatst geposte code het adres van een gederefereerde pointer neemt ontgaat me helemaal, aangezien &(*p) hetzelfde is als p. :P

'E's fighting in there!' he stuttered, grabbing the captain's arm.
'All by himself?' said the captain.
'No, with everyone!' shouted Nobby, hopping from one foot to the other.


  • Elephtera
  • Registratie: Juni 2001
  • Laatst online: 15:29
fout gevonden :)

if ((pqueue[(*el).location].waiting[i]) != 0){
if ((*pqueue[(*el).location].waiting[i]).direction == (*el).state){

door dat te doen los ik het probleem op. gevonden dankzij vyperx. dankje!!

nme -> dat van &(*p) snap ik ook niet van mezelf :) zal zo de hele code nalopen en er mooier uit laten zien, eerst laten werken :P

“An elephant is a mouse with an operating system”


  • VyperX
  • Registratie: Juni 2001
  • Laatst online: 16-02 16:12
Hehe... Graag gedaan :)

En inderdaad wat -NMe- zegt: p->iets tikt (en leest) een stuk makkelijker dan (*p).iets :)

Succes ermee!

My Dwarf Fortress ASCII Reward: ~~@~~####,.".D",.B""


  • H!GHGuY
  • Registratie: December 2002
  • Niet online

H!GHGuY

Try and take over the world...

als je in het vervolg geen gebufferde stream wilt om errors op uit te schrijven gebruik je mss best
"cerr" ;)

ASSUME makes an ASS out of U and ME


  • MSalters
  • Registratie: Juni 2001
  • Laatst online: 27-03 16:52
cerr gaat niet werken. Of je bedoelt stderr, of std::cerr (en dat laatste is C++)

Man hopes. Genius creates. Ralph Waldo Emerson
Never worry about theory as long as the machinery does what it's supposed to do. R. A. Heinlein


  • GX
  • Registratie: Augustus 2000
  • Laatst online: 14-05-2025

GX

Nee.

Misschien leuk voor in het vervolg: compile je code met de -g flag, en leer gdb gebruiken :)

@MSalters: using namespace std; ?

[ Voor 21% gewijzigd door GX op 09-03-2006 10:30 ]


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 17:53

.oisyn

Moderator Devschuur®

Demotivational Speaker

Of download Visual C++ 2005 express gratis waar wél een goede debugger bij zit ;)

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • truegrit
  • Registratie: Augustus 2004
  • Laatst online: 07-04 10:37
.oisyn schreef op donderdag 09 maart 2006 @ 11:30:
Of download Visual C++ 2005 express gratis waar wél een goede debugger bij zit ;)
is dat er dan ook voor linux dan?

hallo


  • MSalters
  • Registratie: Juni 2001
  • Laatst online: 27-03 16:52
Nee. En? Dat is het leuke van standaard C of C++, als het eenmaal bugfree is port het best makkelijk.

[ Voor 4% gewijzigd door MSalters op 09-03-2006 20:27 ]

Man hopes. Genius creates. Ralph Waldo Emerson
Never worry about theory as long as the machinery does what it's supposed to do. R. A. Heinlein


  • mbravenboer
  • Registratie: Januari 2000
  • Laatst online: 06-11-2025
Voor het oplossen van segmentation faults gebruik ik tegenwoordig vaak Valgrind. Valgrind is erg eenvoudig te gebruiken voor profiling en (bepaalde vormen van) debugging. Qua debugging kan Valgrind je bijvoorbeeld vertellen waar je unitialized geheugen gebruikt. Een van de voordelen van Valgrind is dat je niet hoeft te compileren met speciale compiler vlaggen: je kan gewoon direct je executable draaien. Ook voor profiling is het een uitkomst: het is erg eenvoudig in het gebruik, ook als je nog andere statische of dynamische libraries gebruikt.

Zie bijvoorbeeld (zomaar een hit van Google) : http://www.cprogramming.com/debugging/valgrind.html

Blog, Stratego/XT: Program Transformation, SDF: Syntax Definition, Nix: Software Deployment

Pagina: 1