ent_next bug with removed entities?

Posted By: Error014

ent_next bug with removed entities? - 03/29/15 00:41

I get crashes implying that I have an invalid pointer when I go through the list with ent_next after removal of an entity. The easiest way to trigger it is to continously spawn and remove entities. Here's a bit of code that runs without assets that crashes it. Run it, then hold SPACE to start and run the ent_next-loop. Crashes when it hits the str_for_entfile-instruction.

Code:
function exploeffect() {
	wait(3);
	ent_remove(me);
	//ptr_remove(me);		//those make no difference
	//safe_remove(me);
}

void showall() {
	VECTOR t;
	while(key_space) {
		you = ent_next(NULL);
		while(you!=NULL) {
			vec_set(t,your.x);
			vec_to_screen(t,camera);
			draw_text(str_for_entfile(NULL,you),t.x,t.y,COLOR_RED);
		//	draw_text(you->type,t.x,t.y,COLOR_RED);
			you = ent_next(you);	
		}
		wait(1);
	}		
}

void main() {
	VECTOR temp;
	level_load("");
	wait(3);
	on_space = showall;
	VECTOR temp;
	while(1) {
		vec_set(temp,vector(200+random(100),random(100)-50,random(100)-50));
		ent_create(CUBE_MDL,temp,exploeffect);
		wait(-0.3+random(0.5));
	}
}




Interestingly, it does NOT crash when you replace str_for_entfile with you->type. (the line's up there - but commented out - if you want to try).

However, it's not just str_for_entfile that crashes. You could replace it with, say
Code:
c_move(you,vector(1,0,0),nullvector,IGNORE_YOU);


to get it to crash. Or with
Code:
ent_animate(you,"",total_ticks,0);



What I'm saying is, the pointer seems to be invalid. So... Why do I get invalid pointers (from removed entities?) from ent_next?
Posted By: Superku

Re: ent_next bug with removed entities? - 03/29/15 15:59

If you run this modified code
Code:
var new_counter = 0;

void exploeffect()
{
	my.skill1 = 123;
	wait(3);
	my.skill1 = -123;
	ptr_remove(me);
}


void main()
{
	VECTOR temp;
	level_load("");
	wait(3);
	while(1)
	{
		new_counter -= time_step;
		if(new_counter <= 0)
		{
			new_counter = random(5);
			vec_set(temp,vector(200+random(100),random(100)-50,random(100)-50));
			you = ent_create(CUBE_MDL,temp,exploeffect);
			if(your.skill1 != 123 || 1) printf("ohh (%d)",(int)your.skill1);
		}
		for(you = ent_next(NULL); you != NULL; you = ent_next(you))
		{
			if(your.skill1 != 123) printf("hm (%d)",(int)your.skill1);
			vec_set(temp,your.x);
			if(vec_to_screen(temp,camera)) draw_text(str_for_entfile(NULL,you),temp.x,temp.y,COLOR_RED);
		}
		wait(1);
	}
}


you will see that you get three "ohhs" before the first "hm" appears, correlating to the wait(3) in the exploeffect function.
I don't know why though, so sorry for not being able to help at all. :<

EDIT: Oh and the "hm" error message shows a skill value of 0, not -123 as I would have expected.
Posted By: Wjbender

Re: ent_next bug with removed entities? - 03/30/15 11:05

Code:
function exploeffect() 
{
	wait(3);//<--- works now
	//wait(-3)//<--- works if you replace the wait(1) in the main loop with the old wait(random thingy)
	if(me)ent_remove(me);
	//ptr_remove(me);		//those make no difference
	//safe_remove(me);
}

void showall() 
{
	VECTOR t;
	while(key_space) 
	{
		you = ent_next(NULL);
		while(you!=NULL) 
		{
			vec_set(t,your.x);
			vec_to_screen(t,camera);
			draw_text(str_for_entfile(NULL,you),t.x,t.y,COLOR_RED);
		//	draw_text(you->type,t.x,t.y,COLOR_RED);
			you = ent_next(you);	
		}
		wait(1);
	}		
}

void main() 
{
	VECTOR temp;
	level_load("");
	wait(3);
	on_space = showall;
	VECTOR temp;
	while(1) 
	{
		vec_set(temp,vector(200+random(100),random(100)-50,random(100)-50));
		ent_create(CUBE_MDL,temp,exploeffect);
		//wait(-0.3+random(0.5));//<--- posible wait issue here
		wait(1);//<--- works with this wait here
	}
}



some sort of complicated wait problem ,because wait returns back to the calling functions i suppose
Posted By: Wjbender

Re: ent_next bug with removed entities? - 03/30/15 11:45

also if you synchronized the wait value in explodeffect and the main loop wait value , it works , the timing at which things happen overun at the wrong times ?

quite strange
Posted By: jcl

Re: ent_next bug with removed entities? - 03/30/15 16:52

I can not see why you should get a crash in your script. You'll get an error message though: in development mode, the engine detects that you try to display the name of a removed entity. The release version would just display nothing.

If you remove an entity, it's still in the entity list, it just is not visible anymore and has no name or other properties. It only gets physically removed from the list at the next garbage collection, which happens at the end of every cycle.

So the easy solution is to check if the entity has still a name:

Code:
while(you!=NULL) {
	if(you->type == NULL) break;
	...



Hope this explains the problem.
Posted By: Wjbender

Re: ent_next bug with removed entities? - 03/30/15 17:09

so we have to check entities with !=null and type!=null , to be sure we dont use a entity pointer with no data , instead of just !=null ALWAYS ?

or just with the list ?
Posted By: jcl

Re: ent_next bug with removed entities? - 03/31/15 09:24

No, it is not related just to the list, but can also happen in other circumstances. When you have two different actions running on the same entity, and the first action removes the entity at some point, the second action must test the used entity properties - name, position and so on - in order to detect if the entity is still there. Removed entities have no name, no flags, position is zero, and also all other entity properties are nonexistent or zero.
Posted By: Wjbender

Re: ent_next bug with removed entities? - 03/31/15 09:58

thank you jcl

@ error014 wow thanks for finding this !

I am going to write a function or something I can always call when I need to check , this is new for me.
Posted By: Error014

Re: ent_next bug with removed entities? - 04/01/15 20:33

Thank you jcl for the reply and the details! And apologies for saying "crash" when it wasn't a crash - I guess I use the term too liberately laugh

Anyhow, I think that this:

Quote:


If you remove an entity, it's still in the entity list, it just is not visible anymore and has no name or other properties. It only gets physically removed from the list at the next garbage collection, which happens at the end of every cycle.

So the easy solution is to check if the entity has still a name:


Should definitely be in the manual under "ent_next". I sure hope you'd agree that for someone not knowing the details of the engine, this isn't apparent otherwise.



Same goes for this:

Quote:
No, it is not related just to the list, but can also happen in other circumstances. When you have two different actions running on the same entity, and the first action removes the entity at some point, the second action must test the used entity properties - name, position and so on - in order to detect if the entity is still there. Removed entities have no name, no flags, position is zero, and also all other entity properties are nonexistent or zero.


Which I think should be under "ent_remove" in the manual.




Thanks again!

And also big thanks to you two Superku and Wjbender! Good to see I wasn't crazy laugh
Posted By: jcl

Re: ent_next bug with removed entities? - 04/07/15 08:50

Yes, I'll mention this more clearly in the manual.
Posted By: WretchedSid

Re: ent_next bug with removed entities? - 04/09/15 12:47

Here is a drop in fix so you guys don't have to change your ent_next code.

Code:
ENTITY *__ent_next_fixed(ENTITY *ent)
{
	while((ent = ent_next(ent)))
	{
		if(ent->type != NULL)
			return ent;
	}
	
	return NULL;
}

#define ent_next __ent_next_fixed



Edit: Just remembered that Lite-C has result as reserved keyword and that it doesn't support early termination of expressions... Oh well, there goes the elegant function.

Edit 2: Added some elegance back

Edit 3: In case Lite-C ever supports it, here is a elegant three liner:
Code:
ENTITY *__ent_next_fixed(ENTITY *ent)
{
	while((ent = ent_next(ent)) && ent->type == NULL)
		;
	
	return ent;
}

© 2024 lite-C Forums