Jump to content
  • Advertisement
Sign in to follow this  
kozec

Segfault when casting directly

This topic is 2096 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

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.

Share this post


Link to post
Share on other sites
Advertisement
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

Share this post


Link to post
Share on other sites

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.

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!