Gamestudio Links
Zorro Links
Newest Posts
Blobsculptor tools and objects download here
by NeoDumont. 03/28/24 03:01
Issue with Multi-Core WFO Training
by aliswee. 03/24/24 20:20
Why Zorro supports up to 72 cores?
by Edgar_Herrera. 03/23/24 21:41
Zorro Trader GPT
by TipmyPip. 03/06/24 09:27
VSCode instead of SED
by 3run. 03/01/24 19:06
AUM Magazine
Latest Screens
The Bible Game
A psychological thriller game
SHADOW (2014)
DEAD TASTE
Who's Online Now
2 registered members (Quad, aliswee), 835 guests, and 5 spiders.
Key: Admin, Global Mod, Mod
Newest Members
sakolin, rajesh7827, juergen_wue, NITRO_FOREVER, jack0roses
19043 Registered Users
Previous Thread
Next Thread
Print Thread
Rate Thread
Page 1 of 2 1 2
Crash on removing locally created panels using ptr_remove #473390
07/02/18 15:58
07/02/18 15:58
Joined: Apr 2002
Posts: 680
Germany
Turrican Offline OP
User
Turrican  Offline OP
User

Joined: Apr 2002
Posts: 680
Germany
Our game crashes on certain occasions with varying probability (about 50-75% of all cases on affected systems). We collected data from more than 20 test participants – all affected systems run Windows 10, no crashes under Windows 7.

Description: All crashes occur while removing locally created panels. Some of these panels consist of one or more panel elements created at runtime, others have no special elements assigned (see examples below). Crash reproduction failed in dev version; it can only be reproduced in the published version.

We are using a lot of both globally and locally created objects (panels, entities, texts, strings) in our code and so far only removal of local panels seems to lead to crashes.

Could you please give us a hint on how can we debug and fix this? What happens internally during the removal of (local) panels? Does 3DGS support have suitable tools or better ways to analyze these crashes in the published version more precisely?

On a side-note, we have already tried analyzing panel objects using sys_markers and found out that these instructions – unlike others we checked – don’t carry a control byte. How are these handled internally? Do panels allocate memory using sys_malloc? How/where are panels and panel elements stored internally?

Examples

1. Simple fadescreen
Click to reveal..
Code:
// Simple: We create a fullscreen, plain color panel as fade screen during a cutscene. 
// Game crashes [sometimes] after cutscene finished and fadescreen panel is removed.
function intro_sequence()
{
	// ...

	PANEL* _pan_fadescreen = pan_create("red=0; green=0; blue=25; alpha = 100; flags = SHOW | LIGHT | TRANSLUCENT | UNTOUCHABLE;",89);
	_pan_fadescreen.size_x=1920;
	_pan_fadescreen.size_y=1080;
	_pan_fadescreen.scale_x=screen_size.x/1920;
	_pan_fadescreen.scale_y=screen_size.y/1080;

	// ...
	
	while(SEQUENCE_RUNNING)
	{
		if(SCENE==FIRST_SCENE)
		{
			// ...
			_pan_fadescreen.alpha-=10*time_step;
			_pan_fadescreen.alpha=clamp(_pan_fadescreen_alpha,0,100);
			// ...
		}
	
		// ...
		
		if(SCENE==LAST_SCENE)
		{
			// ...
			_pan_fadescreen.alpha+=10*time_step;
			_pan_fadescreen.alpha=clamp(_pan_fadescreen_alpha,0,100);
			// ...
		}
	
		// ...
	
		wait(1);
	}

	// ...
	diag("n Removing panel..."); 	// this is the final line in acklog.txt
	ptr_remove(_pan_fadescreen);
	_pan_fadescreen=NULL;
	diag("OK!"); 	// does not appear in acklog
	// ...
}




2. „Abort Cutscene“ panel
Click to reveal..
Code:
// This one is a bit more complex and also uses additional panel elements instructions, like
// pan_setstring and pan_setcolor. 
// Game crashes [sometimes] after cutscene finished/has been cancelled and message panel is removed.
function cancel_cutscene_message()
{
	// create panel
	PANEL* _pan_skip = pan_create("alpha = 0; flags = ARIGHT | SHOW | TRANSLUCENT | FILTER | SHADOW;",9999);
	_pan_skip.scale_x = screen_size.x/1920;
	_pan_skip.scale_y = screen_size.y/1080;
	
	// create panel elements
	temp=pan_setstring(_pan_skip,0,1900,20,fnt_button_tiny,label_mm_skip);
	pan_setcolor(_pan_skip,1,temp,FONT_COLOR_MM_SKIP);
	
	// fnt_button_tiny: truetype font
	// label_mm_skip: unicode (!) string contained in global text object
	// FONT_COLOR_MM_SKIP: globally defined vector
	
	while(cutscene_active)
	{
		// ...
		// ...
		// wait for end of cutscene or player input
		// ...
		// ...
		
		wait(1);
	}
	
	diag("removing panel..."); 	// this is the final line in acklog.txt
	ptr_remove(_pan_skip);
	diag("OK");	// does not appear in acklog
}


Re: Crash on removing locally created panels using ptr_remove [Re: Turrican] #473395
07/02/18 18:11
07/02/18 18:11
Joined: Aug 2003
Posts: 118
Deutschland
E
Ezzett Offline
Member
Ezzett  Offline
Member
E

Joined: Aug 2003
Posts: 118
Deutschland
What happens if you add a check for null before using pointer remove?
You can also debug your code with the help of the Visual Studio debugger. You just need to convert the code to an engine SDK project. But I don't know how helpful this will be because you can't inspect what happens internally in Acknex and it's not possible to use wait-instructions. So you need to rewrite all functions that use wait.

Re: Crash on removing locally created panels using ptr_remove [Re: Ezzett] #473397
07/02/18 20:34
07/02/18 20:34
Joined: Oct 2007
Posts: 5,210
Ä°stanbul, Turkey
Quad Online
Senior Expert
Quad  Online
Senior Expert

Joined: Oct 2007
Posts: 5,210
Ä°stanbul, Turkey
wait and local pointers are bad news, try tracking those and Ezzett says do a null check if you can't figure it out try storing them on a temporary global variable.


3333333333
Re: Crash on removing locally created panels using ptr_remove [Re: Quad] #473398
07/02/18 20:45
07/02/18 20:45
Joined: Sep 2003
Posts: 6,861
Kiel (Germany)
Superku Offline
Senior Expert
Superku  Offline
Senior Expert

Joined: Sep 2003
Posts: 6,861
Kiel (Germany)
I had a look at the code as well, the pointer is the same as on creation. As an experiment (not sure if it makes sense) I checked the bytes before the pointer as well (negative byte-offset), in case something else overflows and overwrites that panel memory. Those bytes have the same value before ptr_remove.
There's not much going on between panel creation and removal either which could damage memory inbetween.


@Quad: In what way could wait damage a local pointer? I've never had issues with that (despite all the other issues one can have with wait).


"Falls das Resultat nicht einfach nur dermassen gut aussieht, sollten Sie nochmal von vorn anfangen..." - Manual

Check out my new game: Pogostuck: Rage With Your Friends
Re: Crash on removing locally created panels using ptr_remove [Re: Ezzett] #473402
07/03/18 11:54
07/03/18 11:54
Joined: Apr 2002
Posts: 680
Germany
Turrican Offline OP
User
Turrican  Offline OP
User

Joined: Apr 2002
Posts: 680
Germany
Originally Posted By: Ezzett
What happens if you add a check for null before using pointer remove?
You can also debug your code with the help of the Visual Studio debugger. You just need to convert the code to an engine SDK project. But I don't know how helpful this will be because you can't inspect what happens internally in Acknex and it's not possible to use wait-instructions. So you need to rewrite all functions that use wait.

Quite frankly, I can't imagine why the pointer should be NULLed during the execution of the script - unless Quad is right and wait commands allow for random/unwanted modification of pointer contents. Anyway, I will give it a try later.

Concerning the Visual Studio hint: I'm sure it's well-intentioned, but I would like to refrain from that - the project has grown really large at this point and there are quite a lot of wait loops in it. Rewriting all of this would really exceed my time budget. And as you said: You can't inspect what happens internally, anyway.

Originally Posted By: Quad
wait and local pointers are bad news, try tracking those and Ezzett says do a null check if you can't figure it out try storing them on a temporary global variable.

Quad, do you have any examples that show how wait commands can break/overwrite contents of a local pointer...? Never heard of that before, and it would be really critical, since we're using them all over the place.

Re: Crash on removing locally created panels using ptr_remove [Re: Turrican] #473408
07/03/18 14:15
07/03/18 14:15
Joined: Aug 2003
Posts: 118
Deutschland
E
Ezzett Offline
Member
Ezzett  Offline
Member
E

Joined: Aug 2003
Posts: 118
Deutschland
The manual states that pointers can change after calling wait(). Me and you are the only pointers guaranteed to be unchanged.

Wait() returns from a function. I think it is possible that the pointer and the memory area are losing scope after this and it's possible that the memory area is overwritten later.

Maybe you could try creating the panel in a function which doesn't use wait() and pass the panel pointer to another function that uses wait() like in your example, like dependency injection.

Re: Crash on removing locally created panels using ptr_remove [Re: Ezzett] #473411
07/03/18 15:41
07/03/18 15:41
Joined: Sep 2003
Posts: 6,861
Kiel (Germany)
Superku Offline
Senior Expert
Superku  Offline
Senior Expert

Joined: Sep 2003
Posts: 6,861
Kiel (Germany)
Quote:
While the content of local variables is preserved, their addresses change after every wait() because the function runs every time in a different stack frame.

He is not using pointers to local variables, just saving the results of create or memory allocations in local variables (pointers). Those memory addresses are the *content* in the context of the quote and thus are preserved during wait, not the addresses of the actual local variables themselves.


"Falls das Resultat nicht einfach nur dermassen gut aussieht, sollten Sie nochmal von vorn anfangen..." - Manual

Check out my new game: Pogostuck: Rage With Your Friends
Re: Crash on removing locally created panels using ptr_remove [Re: Superku] #473416
07/03/18 19:57
07/03/18 19:57
Joined: Oct 2007
Posts: 5,210
Ä°stanbul, Turkey
Quad Online
Senior Expert
Quad  Online
Senior Expert

Joined: Oct 2007
Posts: 5,210
Ä°stanbul, Turkey
I do not know how lite-c compiles code or wait works internally but yes,

Doing stuff like below sometimes resulted in random crashes:

Code:
void someAction(ENTITY* e){
....
PANEL* a = pan_create(...)
....
while(something){

  //using a/e here sometimes causes strange behaviour, mostly crash

  wait(1);
}
//also here
}



I say "sometimes", mostly it works as intended. I encountered it several times to remember it happening, when you mix wait_for and ptr_remove and juggle pointers around you encounter it at some point. Reducing number of wait/wait_for's or moving things to global scope gets rid of the issue. I only use one wait in main loop and PRAGMA_POINTER since a loong time but:

One workaround was this (apart from moving to global scope):

Code:
void someAction(){
....
PANEL* a = pan_create(...)
me.skill15 = (var)a;
....
while(something){
  a = (PANEL*) me.skill15;
  //no crash anymore when using a
  wait(1);
}
}




Think of the above code as a healthbar panel code for a couple of rts character like entities, just before crash you would see healthbars start positioning incorrectly, then you get the crash. Mostly while trying to remove some of them.

It could be unrelated or related to something else(can't guess what lite-c compiler does) but because of the fix above and moving to global fixing the issue, i always had the impression that somehow pointer the "a" loses it's value. (it could not have been moved around because me.skill15 points to same address, it can only mean "a" loses the address), when a loses the address ptr_remove crashes.

I could not reproduce the "sometimes" scenario in latest A8 but, it could be that it's fixed since then or my test code is not complex enough to confuse lite-c compiler. I am not doing anything complex with lite-c since a long time, and using only one wait even longer than that, so it's most likely fixed in early versions of A7.




Last edited by Quad; 07/03/18 19:58.

3333333333
Re: Crash on removing locally created panels using ptr_remove [Re: Quad] #473417
07/03/18 20:12
07/03/18 20:12
Joined: Feb 2006
Posts: 1,011
Germany
pegamode Offline
Serious User
pegamode  Offline
Serious User

Joined: Feb 2006
Posts: 1,011
Germany
I usually use some defines like that:

Code:
#define _pan_remove(pan) if(pan != NULL) { if(pan->bmap != NULL) { bmap_purge(pan->bmap); ptr_remove(pan->bmap); pan->bmap = NULL; } if(pan->mouse_map != NULL) { bmap_purge(pan->mouse_map); ptr_remove(pan->mouse_map); pan->mouse_map = NULL; } if(pan->target_map != NULL) { bmap_purge(pan->target_map); ptr_remove(pan->target_map); pan->target_map = NULL; } ptr_remove(pan); } pan = NULL
#define _bmap_remove(bmap) if(bmap != NULL) { bmap_purge(bmap); ptr_remove(bmap); } bmap = NULL
#define _ptr_remove(ptr) ptr_remove(ptr); ptr=NULL



So I can do some NULL checks later.

Re: Crash on removing locally created panels using ptr_remove [Re: pegamode] #473423
07/04/18 13:50
07/04/18 13:50
Joined: Jul 2000
Posts: 27,977
Frankfurt
jcl Offline

Chief Engineer
jcl  Offline

Chief Engineer

Joined: Jul 2000
Posts: 27,977
Frankfurt
It's clear that when you use a local panel pointer, and something happens to that panel while the function is still running, it will crash. Such a crash happens randomly, since you're accessing memory with random content. Storing the pointer in a skill is placebo coding, technically it makes no difference.

Such a crash is caused of course by removing the panel, but also by more innocent operations such as removing a bitmap, removing a different panel that shares a bitmap, or saving and loading the game.

If I would design the acknex engine today, I would implement a different allocation and release mechanism. But as it is, ptr_remove just releases the memory of the panel and all its bitmaps. There is no simple way to check if an object pointer is valid or not. The only way is to go through the list of all objects with ptr_first(), and check if the pointer is still in the list.

Re: Crash on removing locally created panels using ptr_remove [Re: jcl] #473428
07/04/18 14:51
07/04/18 14:51
Joined: Sep 2003
Posts: 6,861
Kiel (Germany)
Superku Offline
Senior Expert
Superku  Offline
Senior Expert

Joined: Sep 2003
Posts: 6,861
Kiel (Germany)
Originally Posted By: jcl
removing a different panel that shares a bitmap [...]
ptr_remove just releases the memory of the panel and all its bitmaps.

Hmm what does that mean exactly when we look at the following cases:
Code:
=== CASE 1 === 
BMAP* compass_map = "compass.pcx"; 
PANEL* aircraft_pan =
{
   bmap = compass_map; // compass_map as panel background
   flags = SHOW;
}

=== CASE 2 === 
Same as in 1 but bmap pointer (globally or locally created) dynamically assigned - most likely the same?

=== CASE 3 === 
PANEL* splashscreen = { bmap = "splash.pcx"; } // creates a bmap splash_pcx

=== CASE 4 === 
PANEL* pnlDynamic = pan_create("...");
no panel background bmap
pan_setwindow(pnlDynamic, ...,BMAPPOINTER,...);



In which of those 4 cases are bitmaps being freed?


EDIT:
Originally Posted By: jcl
It's clear that when you use a local panel pointer, and something happens to that panel while the function is still running, it will crash.

I do not understand what this means, can you rephrase that sentence please? confused
In Turrican's situation the panel is created locally inside the function, not used in or "exposed" to any other function. Yet it crashes on removal. (EDIT2: Panel confirmed to be still in the C_LINK list before ptr_remove.)

Last edited by Superku; 07/05/18 14:17.

"Falls das Resultat nicht einfach nur dermassen gut aussieht, sollten Sie nochmal von vorn anfangen..." - Manual

Check out my new game: Pogostuck: Rage With Your Friends
Re: Crash on removing locally created panels using ptr_remove [Re: Superku] #473443
07/06/18 23:08
07/06/18 23:08
Joined: Sep 2003
Posts: 9,859
F
FBL Offline
Senior Expert
FBL  Offline
Senior Expert
F

Joined: Sep 2003
Posts: 9,859
I think the point is you *could* do something harmful (like removing a referenced BMAP) in some other function which is running during wait(1).

If the examples above are to be considered standalone, meaning nothing else is running during the wait(1), this of course does not apply.

Page 1 of 2 1 2

Moderated by  old_bill, Tobias 

Gamestudio download | chip programmers | Zorro platform | shop | Data Protection Policy

oP group Germany GmbH | Birkenstr. 25-27 | 63549 Ronneburg / Germany | info (at) opgroup.de

Powered by UBB.threads™ PHP Forum Software 7.7.1