08 Nov, 2007, Sandi wrote in the 1st comment:
Votes: 0
I'm sure you're familiar with:

for ( obj = ch->carrying; obj != NULL; obj= obj_next )
{
obj_next = obj->next_content;

……… more code that does something ………
}


I have an old bug report from the ROM list where someone had trouble with this while making corpses. Seems another function modified the obj_next and caused a crash. The posted fix was this:

for ( obj = ch->carrying; obj; obj = obj->next_content )
{
…….. some code here ……..
}


Now, I have 32 occurrences of the first version, and I'm wondering if there's a reason for writing it that way, or if it's okay to replace them all with the second version, just for consistency (and possible bug-proofing against future changes).
08 Nov, 2007, Caius wrote in the 2nd comment:
Votes: 0
The first version is used for when you're removing items from the list within the 'for' loop. By storing the pointer to the next item in obj_next you make sure that you don't invalidate the list.

So the short answer is that if you use the second version, and 'obj' is deleted within the loop, then 'obj = obj->next_content' will give you trouble. "Trouble" means a crash if you're lucky, and corrupted data if you're unlucky.
08 Nov, 2007, Sandi wrote in the 3rd comment:
Votes: 0
Thanks.

Since they've been fine for 9 years, I'll leave them all alone. Seems maybe the poster was fixing a symptom….
08 Nov, 2007, Caius wrote in the 4th comment:
Votes: 0
Quote
Seems another function modified the obj_next and caused a crash.

Yes, that would usually cause a crash. obj_next should remain untouched, or else there's no point in using this technique.
08 Nov, 2007, Mister wrote in the 5th comment:
Votes: 0
Even if obj_next itself is untouched, the variable it points to can be modified/removed, and that will cause problems, too. An example with characters instead of objects: if "ch" is a player, and "ch_next" the pet of that character, deleting the player is likely to delete the pet, too, so ch_next will be invalid.

Basically, if you use "obj=obj->next_content", you must not remove obj from that linked list. If obj can be removed, then you need to use "obj=obj_next" instead, but then you can't remove obj_next from the list.
14 Nov, 2007, BumpInTheNight wrote in the 6th comment:
Votes: 0
Incidentally, I found bug in stock rom2.4b's violence_update where this protection wasn't completely implemented.

for ( ch = char_list; ch != NULL; ch = ch->next )
{
ch_next = ch->next;


that for loop should be ending with ch=ch_next. May resolve some people's mystery bugs with fatal damage to the attacker during combat rounds if they've made such situations possible through modification. ;)
14 Nov, 2007, Scandum wrote in the 7th comment:
Votes: 0
Mister said:
Basically, if you use "obj=obj->next_content", you must not remove obj from that linked list. If obj can be removed, then you need to use "obj=obj_next" instead, but then you can't remove obj_next from the list.


Not necessarily, what I do:

for (obj = mud->f_obj ; obj ; obj = mud->update_obj)
{
mud->update_obj = obj->next;


void extract_obj( OBJ_DATA *obj )         
{
if (mud->update_obj == obj)
{
mud->update_obj = obj->next;
}


As should be obvious, you can only use it with low level routines.
0.0/7