Jump to content

  • Log In with Google      Sign In   
  • Create Account


- - - - -

Segfault when casting directly


Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

  • You cannot reply to this topic
6 replies to this topic

#1 kozec   Members   -  Reputation: 118

Like
0Likes
Like

Posted 21 December 2012 - 03:41 PM

Hi.

I'm trying to use AngelScript as scripting language in my one-day-it-will-be-game and I encountered weird problem today.

I have two registered C++ classes, EventSource and ASConsole derived from it and registered method addListener(EventSource* source, ...)

 

Now, if I call addListener like this...





ASConsole@ console; // This is actually global variable
void main() {
	EventSource@ s = cast<EventSource>(console);
	module.addListener(s, ET_READLINE, onLine);
	loop();
}

... everything is OK. ASConsole is dynamic_cast-ed to EventSource, pointer is returned and addListener recieves same pointer. But, if I do this... 





ASConsole@ console; // This is actually global variable
void main() {
	module.addListener(cast<EventSource>(console), ET_READLINE, onLine);
	loop();
}
 

... dynamic_cast returns one pointer (0x81a240), addListener recieves something else (0x8c5f98) and entire thing segfaults.

 

Am I doing something wrong? And, is there possibility to prevent segfault when this wrong method is used? I would like to let users to use some in-game scripting, but I really don't want to let them crash entire thing.



Sponsor:

#2 Andreas Jonsson   Moderators   -  Reputation: 3227

Like
0Likes
Like

Posted 21 December 2012 - 05:54 PM

Both ways should be equivalent. It would appear you've encountered a bug in the compiler.

I'll investigate this.
AngelCode.com - game development and more - Reference DB - game developer references
AngelScript - free scripting library - BMFont - free bitmap font generator - Tower - free puzzle game

#3 Andreas Jonsson   Moderators   -  Reputation: 3227

Like
0Likes
Like

Posted 21 December 2012 - 06:34 PM

I wasn't able to reproduce the problem.

Does this code represent well what you have? If not, can you spot what is different?
class EventSource
{
public:
	EventSource() {refCount = 1; value = 42;};
	virtual ~EventSource() {}
	virtual void AddRef() {refCount++;}
	virtual void Release() {if( --refCount == 0 ) delete this;}
	int refCount;

	int value;
};

class ASConsole : public EventSource
{
public:
	static ASConsole *factory() { return new ASConsole(); }
	EventSource *opCast() { return this; }
};

bool Test()
{
	bool fail = false;
	int r;
	asIScriptEngine *engine;

	CBufferedOutStream bout;
	COutStream out;

	// http://www.gamedev.net/topic/636163-segfault-when-casting-directly/
	{
		engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);
		engine->SetMessageCallback(asMETHOD(COutStream,Callback), &out, asCALL_THISCALL);
		engine->RegisterGlobalFunction("void assert(bool)", asFUNCTION(Assert), asCALL_GENERIC);
		RegisterStdString(engine);

		engine->RegisterObjectType("EventSource", 0, asOBJ_REF);
		engine->RegisterObjectBehaviour("EventSource", asBEHAVE_ADDREF, "void f()", asMETHOD(EventSource, AddRef), asCALL_THISCALL);
		engine->RegisterObjectBehaviour("EventSource", asBEHAVE_RELEASE, "void f()", asMETHOD(EventSource, Release), asCALL_THISCALL);
		engine->RegisterObjectProperty("EventSource", "int value", asOFFSET(EventSource, value));

		engine->RegisterObjectType("ASConsole", 0, asOBJ_REF);
		engine->RegisterObjectBehaviour("ASConsole", asBEHAVE_FACTORY, "ASConsole @f()", asFUNCTION(ASConsole::factory), asCALL_CDECL);
		engine->RegisterObjectBehaviour("ASConsole", asBEHAVE_ADDREF, "void f()", asMETHOD(ASConsole, AddRef), asCALL_THISCALL);
		engine->RegisterObjectBehaviour("ASConsole", asBEHAVE_RELEASE, "void f()", asMETHOD(ASConsole, Release), asCALL_THISCALL);
		engine->RegisterObjectBehaviour("ASConsole", asBEHAVE_REF_CAST, "EventSource@+ f()", asMETHOD(ASConsole, opCast), asCALL_THISCALL);

		asIScriptModule *mod = engine->GetModule("test", asGM_ALWAYS_CREATE);
		mod->AddScriptSection("test",
			"enum E { ET_READLINE = 24 } \n"
			"class Module { \n"
			"  void addListener(EventSource @s, E type, string line) {\n"
			"    assert(line == 'test'); \n"
			"    assert(type == ET_READLINE); \n"
			"    assert(s.value == 42); \n"
			"    EventSource @c = cast<EventSource>(console); \n"
			"    assert(c is s); \n"
			"  } \n"
			"} \n"
			"Module module; \n"
			"string onLine = 'test'; \n"
			"ASConsole @console = ASConsole(); \n"
			"void main() \n"
			"{ \n"
			"  module.addListener(cast<EventSource>(console), ET_READLINE, onLine); \n"
			"} \n");
		r = mod->Build();
		if( r < 0 )
			TEST_FAILED;

		r = ExecuteString(engine, "main()", mod);
		if( r != asEXECUTION_FINISHED )
			TEST_FAILED;

		engine->Release();
	}

 	return fail;
}

- What version of AngelScript are you using?
- On what OS are you developing your code?
- With what compiler?

Edited by Andreas Jonsson, 21 December 2012 - 06:47 PM.

AngelCode.com - game development and more - Reference DB - game developer references
AngelScript - free scripting library - BMFont - free bitmap font generator - Tower - free puzzle game

#4 kozec   Members   -  Reputation: 118

Like
0Likes
Like

Posted 25 December 2012 - 05:41 AM

Hello again. I'm sorry for my late response, there were some trouble with my account and I was not able to login.

Andreas, I modified your code a little so now its manifest same problem. Main difference is that my addListener method is in c++, not AS. Here is code and here is zipped eclipse project as well.
When I launch this code, both addListener calls...

EventSource@ x = cast(console);
addListener(x, ET_READLINE);               // source is first parameter
addListener(cast(console), ET_READLINE);   // source is first parameter

... should yield same results. In fact, output is:

ASRefCast: returning 0x940010
addListener: source = 0x940010
addListener: source.value = 2a

ASRefCast: returning 0x940010
addListener: source = 0x956400
addListener: source.value = 0

Value passed from typecasting function to addListener gets somehow changed sad.png

I'm on ArchLinux (3.6.9-1-ARCH), x86_64, using angelscript 2.25.2, built from AUR. As compiler, g++ (from gcc package, version 4.7.2) is used.



#5 Andreas Jonsson   Moderators   -  Reputation: 3227

Like
0Likes
Like

Posted 25 December 2012 - 11:29 AM

Thanks for providing the additional information.

It's possible that this is a 64bit specific bug. I'll try to reproduce it on the 64bit Linux platform I have at my disposal.
AngelCode.com - game development and more - Reference DB - game developer references
AngelScript - free scripting library - BMFont - free bitmap font generator - Tower - free puzzle game

#6 Andreas Jonsson   Moderators   -  Reputation: 3227

Like
0Likes
Like

Posted 25 December 2012 - 01:25 PM

It turns out the problem wasn't 64bit specific after all.<br /><br />With the code you provided I found the problem. It was related to passing a handle stored in a temporary variable to a function that expected a non-handle inout reference. In this specific case the compiler didn't properly dereference the pointer on the stack so the function ended up receiving a pointer to the handle, rather than the object itself.<br /><br />I've fixed this problem in revision 1522.<br /><br />Thanks for the help in reproducing the problem.
AngelCode.com - game development and more - Reference DB - game developer references
AngelScript - free scripting library - BMFont - free bitmap font generator - Tower - free puzzle game

#7 kozec   Members   -  Reputation: 118

Like
0Likes
Like

Posted 29 December 2012 - 03:03 PM

Great. Thank you very much for your help :)






Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.



PARTNERS