On Tue, 23 Apr 2002, Daniel Byer wrote:
> Well, I finally finished my tracking code. So, I compiled it, ran into
> some stupid little errors, fixed them, and finally got the code working.
> Only to discover that the mud went in to a horrible, horrible crash (to
> the best of my knowledge). The only feedback I got from the terminal was
> "Bus error"
>
> Those are generally bad. :P
I agree. I haven't seen a good bus error in quite a while.
> I'm going to post the relevant code/location, and the feedback I
> received.
>
> In "void move_char( CHAR_DATA *ch, int door, bool follow )" in
> "act_move.c", directly before "char_from_room( ch );" and "char_to_room
> ( ch, to_room );"
> /* TRACKING CODE. COMPLETE(?). */
> if ( do_track ) {
> send_to_char( "DO_TRACK IS TRUE\n\r", ch );
> if ( in_room->tracking ) {
This should be a linked list search. Just looking at the first entry will
not work how you want if somebody else enters the room before you leave.
> if ( in_room->tracking->player == ch ) {
Small gotcha here... Using a pointer to ch isn't gonna work correctly
unless you go through and remove every track this character has when
they exit the mud (fairly computationally expensive).
> in_room->tracking->dir_to = door;
> in_room->tracking->age = 0;
> }
> else {
> if ( ( inTrack = alloc_mem( sizeof( TRACK_DATA ) ) ) !=
> NULL ) {
> inTrack->player = ch;
> inTrack->age = 0;
> inTrack->dir_to = door;
> in_room->tracking->next = inTrack;
Don't forget to set "inTrack->next = NULL;". And you'll probably want
to also initialize inTrack->dir_from to keep from getting weird results.
I'd suggest moving half of this allocation/initialization code to it's
own function, similar to all the new_XXX() in recycle.c.
> send_to_char( "Allocated. First block.\n\r", ch );
> }
> }
> }
> else {
> if ( ( inTrack = alloc_mem( sizeof( TRACK_DATA ) ) ) !=
> NULL ) {
> inTrack->player = ch;
> inTrack->age = 0;
> inTrack->dir_to = door;
> in_room->tracking = inTrack;
> send_to_char( "Allocated. Second block.\n\r", ch );
> }
> }
>
> if ( to_room->tracking ) {
> if ( to_room->tracking->player == ch ) {
> to_room->tracking->dir_from = rev_dir[door];
> to_room->tracking->age = 0;
Same comments about the linked list search apply here also. This will
not work as you want if somebody else enters the room before you enter
it again.
> }
> else {
> if ( ( toTrack = alloc_mem( sizeof( TRACK_DATA ) ) ) !=
> NULL ) {
> toTrack->player = ch;
> toTrack->age = 0;
> toTrack->dir_from = rev_dir[door];
> to_room->tracking->next = toTrack;
> send_to_char( "Allocated. Third block.\n\r", ch );
> }
> }
> }
> else {
> if ( ( toTrack = alloc_mem( sizeof( TRACK_DATA ) ) ) !=
> NULL ) {
> toTrack->player = ch;
> toTrack->age = 0;
> toTrack->dir_from = rev_dir[door];
> to_room->tracking = inTrack;
> send_to_char( "Allocated. Fourth block.\n\r", ch );
> }
> }
>
> }
> /* END TRACKING CODE */
>
> do_track is just a bool to determine if the tracking code should be
> executed. An example, is do_track will be false if ch is an immortal.
> The "Allocated. X block" send_to_char()s are there just so I can walk
> around and determine if things are supposedly working.
>
> the track_data struct, located in "merc.h":
> /* BEGIN TRACK STRUCT */
> struct track_data
> {
> CHAR_DATA * player; /* player to pass through exit
> */
> sh_int age; /* age of tracks */
> sh_int dir_to; /* direction tracks go to */
> sh_int dir_from; /* direction tracks come from */
> TRACK_DATA * next; /* next tracking data, say, if another
> player passes through exit */
> };
> /* END TRACK STRUCT */
>
> room_index_data contains a TRACK_DATA struct, with the name "tracking."
>
> In "void load_rooms( FILE *fp )" in "db.c", at very bottom, right before
> "iHash = vnum % MAX_KEY_HASH;":
> /* This is to initialize the tracking struct.. was causing funny things
> to happen before I added this line */
> pRoomIndex->tracking = NULL;
> /* end */
>
> In "void reset_area( AREA_DATA *pArea )" in "db.c", case 'R': directly
> after the "for ( d0 = 0; d0 < pReset->arg2 - 1; d0++ )" loop finishes
> (this code is located AFTER the loop, and AFTER the bracket directly
> after it, thus past the if/else statement):
Hmm.. I don't see the if/else statement you're referring to in stock code.
Are you saying this code is inside case 'R'? If so, it shouldn't be.
> /*
> * This is the tracking reset code. Every PULSE_AREA, we
> update/destroy the tracks
> */
> if ( pRoomIndex->tracking ) {
This if is not necessary. The for takes care of it.
> for ( ; !pRoomIndex->tracking; ) { /* I just saw this now.. should I
> not have the ! in there? */
Correct. The ! should not be there.
This loop has quite a few problems.
What if you don't delete the first track? Then pRoomIndex->tracking
will be true still (after you fix the loop and take out the !), and
the loop will continue forever. Actually, this applies to any entry
you don't delete, after you have deleted everything in front of it.
On the other hand, if you do delete the first track, it will try to
free that same memory yet again (see the note below about resetting
pRoomIndex->tracking to NULL to fix this).
Now on to my biggest problem with the loop: It doesn't handle deleting
the 2nd or 3rd or whatever entry without deleting the 1st.
The loop should be much more complex to take care of iterating through
the list and deleting entries out of it correctly. The rest of the
stuff in the loop looks good though.
> killTrack = FALSE;
> pRoomIndex->tracking->age += pRoomIndex->tracking->age;
I don't understand what this line is doing. Doubling the age? Why?
Didn't you set it to 0 before? 0 + 0 = 0. Did you mean += 1 instead?
> switch ( pRoomIndex->sector_type ) {
> case 0: case 1:
> if ( pRoomIndex->tracking->age >= ( 3 * PULSE_AREA ) )
> {
> killTrack = TRUE;
> break;
> }
> case 2: case 4: case 5:
> if ( pRoomIndex->tracking->age >= ( 7 * PULSE_AREA ) )
> {
> killTrack = TRUE;
> break;
> }
> case 3:
> if ( pRoomIndex->tracking->age >= ( 15 * PULSE_AREA ) )
> {
> killTrack = TRUE;
> break;
> }
> case 10:
> if ( pRoomIndex->tracking->age >= ( 10 * PULSE_AREA ) )
> {
> killTrack = TRUE;
> break;
> }
> }
>
> if ( killTrack )
> {
> if ( pRoomIndex->tracking->next ) {
> if ( ( tmpTrack = alloc_mem( sizeof( *tmpTrack ) ) ) !=
> NULL ) {
Uhhh.. what's this????
> tmpTrack = pRoomIndex->tracking->next;
Oops.. Just lost the memory we allocated on the last line. (BAD THING!)
> free_mem( pRoomIndex->tracking, sizeof
> ( *pRoomIndex->tracking ) );
> pRoomIndex->tracking = tmpTrack;
> }
> }
> else {
> free_mem( pRoomIndex->tracking, sizeof
> ( *pRoomIndex->tracking ) );
Forgot to set "pRoomIndex->tracking = NULL;"
> }
> }
> }
> }
> /* END */
I don't know what would be causing the bus error, but try fixing
some of this stuff and see if it helps.
On a side note: This was a very good email. A very detailed description
of the problem and all the relevant code listed. If only everyone
who posted with problems could do this.
Dennis