Angband.oook.cz
Angband.oook.cz
AboutVariantsLadderForumCompetitionComicScreenshotsFunniesLinks

Go Back   Angband Forums > Angband > Development

Reply
 
Thread Tools Display Modes
Old April 3, 2016, 12:59   #1
calris
Adept
 
Join Date: Mar 2016
Posts: 194
calris is on a distinguished road
Crash due to referencing object deleted by drop_near()

Rather than clutter the Vanilla board, I'll discuss my findings here. Original thread is here

In summary, there is a repeatable crash if a monster picks up an object and that object is destroyed when the monster dies due to lack of floor space. The 'birth_stacking' flag seems to be ignored (the save file in the referenced thread has stacking on'.

In obj-pile.c in drop_near() there are a couple of chunks of code like this:

Code:
		/* Message */
		msg("The %s %s.", o_name,
			VERB_AGREEMENT(dropped->number, "disappears", "disappear"));

		/* Debug */
		if (player->wizard) msg("Breakage (no floor space).");

		/* Failure */
		if (dropped->known) {
			delist_object(cave_k, dropped->known);
			object_delete(&dropped->known);
		}
		delist_object(c, dropped);
		object_delete(&dropped);
		return;
and in delist_object() we have:

Code:
	/* Don't delist an actual object if it still has a listed known object */
	if ((c == cave) && cave_k->objects[obj->oidx]) return;

	c->objects[obj->oidx] = NULL;
	obj->oidx = 0;
I'm thinking that when an object is picked up by a monster, it's not being removed from the 'cave' completely.

In mon_move.c in process_monster_grab_objects(), the code which performs the pick-up is

Code:
square_excise_object(c, ny, nx, obj);
monster_carry(c, mon, obj);
square_note_spot(c, ny, nx);
square_light_spot(c, ny, nx);
square_excise_object() just calls pile_excise() - but nowhere does the code seem to touch cave_k->objects[obj->oidx]

Hopefully this helps track down this nasty
calris is offline   Reply With Quote
Old April 3, 2016, 15:04   #2
Nick
Vanilla maintainer
 
Nick's Avatar
 
Join Date: Apr 2007
Location: Canberra, Australia
Age: 52
Posts: 6,652
Donated: $60
Nick is on a distinguished road
Quote:
Originally Posted by calris View Post
I'm thinking that when an object is picked up by a monster, it's not being removed from the 'cave' completely.

In mon_move.c in process_monster_grab_objects(), the code which performs the pick-up is

Code:
square_excise_object(c, ny, nx, obj);
monster_carry(c, mon, obj);
square_note_spot(c, ny, nx);
square_light_spot(c, ny, nx);
square_excise_object() just calls pile_excise() - but nowhere does the code seem to touch cave_k->objects[obj->oidx]

Hopefully this helps track down this nasty
OK, thanks for this - I think I have tracked it down, eventually. It's actually kind of the opposite of this. The process_monster_grab_objects() code is fine, but the drop_near() code needed a call to square_excise_object() to remove the about-to-be-deleted object from the place where the player thought it was...

So what actually happened was this:
  1. Master Rogue looted the vault, in the process picking up a Ring of Resist Poison which the character had already detected
  2. Master Rogue wanders into LoS and gets fire bolted
  3. The masses of loot he has collected doesn't fit in the small space available, even with stacking, so stuff gets deleted, including the ring
  4. The bug occurs - the character sees the ring drop, but the character's knowledge of the ring's new whereabouts doesn't update, and it's still recorded as sitting inside the vault room
  5. While the map is being redrawn, a check is done of what the character thinks is there, and comes up with an invalid memory call, because it's been wiped.

Bug is fixed in development
__________________
One Ring to rule them all, One Ring to find them,
One Ring to bring them all and in the darkness bind them.
Nick is offline   Reply With Quote
Old April 5, 2016, 15:31   #3
PowerWyrm
Veteran
 
PowerWyrm's Avatar
 
Join Date: Apr 2008
Posts: 2,051
PowerWyrm is on a distinguished road
No idea if it's related to this bug at all, since this happened in PWMAngband and not in Vanilla Angband, but the code is roughly the same. I was clearing a mixed n/M pit when the game crashed in drop_near() during monster death:

Code:
    /* Drop objects being carried */
    obj = mon->held_obj;
    while (obj)
    {
        next = obj->next;

        /* Object no longer held */
        obj->held_m_idx = 0;
        pile_excise(&mon->held_obj, obj);

        ...

        drop_near(p, c, obj, 0, mon->fy, mon->fx, true, DROP_FADE);
        obj = next;
    }

    /* Forget objects */
    mon->held_obj = NULL;
Traking down the problem in debug mode, it seems that the "obj" pointer is invalid and probably points to something that has already been freed. No idea why this happens...
__________________
PWMAngband variant maintainer - check http://www.mangband.org/forum/viewforum.php?f=9 to learn more about this new variant!
PowerWyrm is offline   Reply With Quote
Old April 5, 2016, 15:49   #4
Nick
Vanilla maintainer
 
Nick's Avatar
 
Join Date: Apr 2007
Location: Canberra, Australia
Age: 52
Posts: 6,652
Donated: $60
Nick is on a distinguished road
Quote:
Originally Posted by PowerWyrm View Post
Traking down the problem in debug mode, it seems that the "obj" pointer is invalid and probably points to something that has already been freed. No idea why this happens...
This seems likely to be the same as in V - see my previous post. All the cases of
Code:
		if (dropped->known) {
			delist_object(cave_k, dropped->known);
			object_delete(&dropped->known);
		}
in drop_near() need to be
Code:
		if (dropped->known) {
			if (dropped->known->iy && dropped->known->ix)
 				square_excise_object(cave_k, dropped->known->iy, dropped->known->ix, dropped->known);
			delist_object(cave_k, dropped->known);
			object_delete(&dropped->known);
		}
__________________
One Ring to rule them all, One Ring to find them,
One Ring to bring them all and in the darkness bind them.
Nick is offline   Reply With Quote
Old April 6, 2016, 10:16   #5
PowerWyrm
Veteran
 
PowerWyrm's Avatar
 
Join Date: Apr 2008
Posts: 2,051
PowerWyrm is on a distinguished road
Quote:
Originally Posted by Nick View Post
This seems likely to be the same as in V - see my previous post.
It's not the case (especially since I didn't implement object lists like in V). I think I found the problem (except from drop_near):

Code:
	/* Give it to the floor */
	if (!floor_carry(c, by, bx, dropped, false)) ...

	/* Sound */
	sound(MSG_DROP);

	/* Message when an object falls under the player */
	if (verbose && (c->squares[by][bx].mon < 0))
		/* Check the item still exists and isn't ignored */
		if (c->objects[dropped->oidx] && !ignore_item_ok(dropped))
			msg("You feel something roll beneath your feet.");
What happened is that the monster dropped something (probably gold since there were a lot of Ms) and didn't have space on the spot so it rolled under the character and got combined with a similar object.

Code:
	/* Scan objects in that grid for combination */
	for (obj = square_object(c, y, x); obj; obj = obj->next) {
		/* Check for combination */
		if (object_similar(obj, drop, OSTACK_FLOOR)) {
			/* Combine the items */
			object_absorb(obj, drop);

			/* Result */
			return true;
		}

		/* Count objects */
		n++;
	}
The problem is that when two objects are combined, the second object is deleted:

Code:
	/* Add together the item counts */
	obj1->number = (total < z_info->stack_size ? total : z_info->stack_size);

	object_absorb_merge(obj1, obj2);
	object_delete(&obj2);
The result is that object "dropped" has been wiped in drop_near(), but is referenced to display the "You feel something roll beneath your feet." message. IIRC this was working in 4.0.4: the code was using some "ignorable" variable to keep state prior to object deletion.
__________________
PWMAngband variant maintainer - check http://www.mangband.org/forum/viewforum.php?f=9 to learn more about this new variant!
PowerWyrm is offline   Reply With Quote
Old April 6, 2016, 13:25   #6
PowerWyrm
Veteran
 
PowerWyrm's Avatar
 
Join Date: Apr 2008
Posts: 2,051
PowerWyrm is on a distinguished road
FYI: commit ec27572 introduced the bug.
__________________
PWMAngband variant maintainer - check http://www.mangband.org/forum/viewforum.php?f=9 to learn more about this new variant!
PowerWyrm is offline   Reply With Quote
Reply


Currently Active Users Viewing This Thread: 1 (0 members and 1 guests)
 
Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump

Similar Threads
Thread Thread Starter Forum Replies Last Post
borg out of sync sometimes due to lag in update on p_ptr->inventory[] APWhite Development 1 September 10, 2011 22:39
Ridiculous death due, in my opinion, to flawed design. Vogrim Vanilla 168 January 4, 2011 23:46
Amazing character but still YASD due to NAsTY monster Thraalbee AAR 12 September 11, 2010 10:13
object list fyonn Vanilla 17 June 23, 2010 17:04
28 tickets due by May 31. PaulBlay Development 0 May 5, 2009 22:26


All times are GMT +1. The time now is 22:42.


Powered by vBulletin® Version 3.8.7
Copyright ©2000 - 2017, vBulletin Solutions, Inc.