Crash when executing script (free(): invalid next size)
Hi,
I have a global function that is causing a crash when it is executed on linux or mac.
It is registered like this:
[source lang="cpp"]engine->RegisterGlobalFunction("void AddIconMarker( const string &in, const string &in, dimension2di frameDimension, int frame )",
asFUNCTIONPR(CBanner::AddIconMarker, (const std::string &, const std::string &, dimension2di, int), void), asCALL_CDECL);[/source]
In windows, a call like the following works fine:
[source lang="cpp"]AddIconMarker( "$NONE$", "GUI/InteractionIcons.png", dimension2di(16,16), 9 );[/source]
However, on linux and mac this results in a crash with the error 'free(): invalid next size'
Backtrace:
0 0xb7fdd424 __kernel_vsyscall
1 0xb7ace1ef raise
2 0xb7ad1835 abort
3 0xb7b092fa ??
4 0xb7b13e42 ??
5 0xb6e5e84c asCScriptEngine::CallFree /home/tom/kagscript/3rd/angelscript/sdk/angelscript/source/as_scriptengine.cpp 3466
6 0xb6e8ec25 CallSystemFunction /home/tom/kagscript/3rd/angelscript/sdk/angelscript/source/as_callfunc.cpp 498
7 0xb6e3d8ae asCContext::ExecuteNext /home/tom/kagscript/3rd/angelscript/sdk/angelscript/source/as_context.cpp 2024
8 0xb6e3bea6 asCContext::Execute /home/tom/kagscript/3rd/angelscript/sdk/angelscript/source/as_context.cpp 1092
9 0xb6a34f6e asScript::ExecuteWithDebug /home/tom/kagscript/trunk/Scripting/asScript.cpp 180
It gets to CallSystemFunction for the AddIconMarker function, then tries to CallFree and we get this crash.
I've stepped through the code and verified that other global functions registered in a similar way have been executed correctly, with the same CallFree call taking place.
For example, the following regiestered global function works fine on all 3 platforms:
[source lang="cpp"]engine->RegisterGlobalFunction("void AddColorMarker( const string &in, SColor color )",
asFUNCTIONPR(CBanner::AddColorMarker, (const std::string &, SColor), void), asCALL_CDECL);[/source]
I'm not really sure what's going on and would really appreciate any help you can provide.
I have a global function that is causing a crash when it is executed on linux or mac.
It is registered like this:
[source lang="cpp"]engine->RegisterGlobalFunction("void AddIconMarker( const string &in, const string &in, dimension2di frameDimension, int frame )",
asFUNCTIONPR(CBanner::AddIconMarker, (const std::string &, const std::string &, dimension2di, int), void), asCALL_CDECL);[/source]
In windows, a call like the following works fine:
[source lang="cpp"]AddIconMarker( "$NONE$", "GUI/InteractionIcons.png", dimension2di(16,16), 9 );[/source]
However, on linux and mac this results in a crash with the error 'free(): invalid next size'
Backtrace:
0 0xb7fdd424 __kernel_vsyscall
1 0xb7ace1ef raise
2 0xb7ad1835 abort
3 0xb7b092fa ??
4 0xb7b13e42 ??
5 0xb6e5e84c asCScriptEngine::CallFree /home/tom/kagscript/3rd/angelscript/sdk/angelscript/source/as_scriptengine.cpp 3466
6 0xb6e8ec25 CallSystemFunction /home/tom/kagscript/3rd/angelscript/sdk/angelscript/source/as_callfunc.cpp 498
7 0xb6e3d8ae asCContext::ExecuteNext /home/tom/kagscript/3rd/angelscript/sdk/angelscript/source/as_context.cpp 2024
8 0xb6e3bea6 asCContext::Execute /home/tom/kagscript/3rd/angelscript/sdk/angelscript/source/as_context.cpp 1092
9 0xb6a34f6e asScript::ExecuteWithDebug /home/tom/kagscript/trunk/Scripting/asScript.cpp 180
It gets to CallSystemFunction for the AddIconMarker function, then tries to CallFree and we get this crash.
I've stepped through the code and verified that other global functions registered in a similar way have been executed correctly, with the same CallFree call taking place.
For example, the following regiestered global function works fine on all 3 platforms:
[source lang="cpp"]engine->RegisterGlobalFunction("void AddColorMarker( const string &in, SColor color )",
asFUNCTIONPR(CBanner::AddColorMarker, (const std::string &, SColor), void), asCALL_CDECL);[/source]
I'm not really sure what's going on and would really appreciate any help you can provide.
I believe the problem is related to the dimension2di type being passed by value. Probably AngelScript is not handling it the way that the gnuc expects it to be handled on Linux and Mac.
How has this type been registered with AngelScript, and what does the C++ implementation look like?
How has this type been registered with AngelScript, and what does the C++ implementation look like?
AngelCode.com - game development and more - Reference DB - game developer references
AngelScript - free scripting library - BMFont - free bitmap font generator - Tower - free puzzle game
Thanks for the quick response.
We use the engine Irrlicht, and dimension2di is provided by it. We're using bindings provided by a 3rd party for it.
The following PB contains the the contents of the asDimension2d.cpp file that does this:
http://pastebin.com/5L44p0Vt
If you need to see the implementation, it is here:
http://pastebin.com/AwxqzaJS
We use the engine Irrlicht, and dimension2di is provided by it. We're using bindings provided by a 3rd party for it.
The following PB contains the the contents of the asDimension2d.cpp file that does this:
http://pastebin.com/5L44p0Vt
If you need to see the implementation, it is here:
http://pastebin.com/AwxqzaJS
Try registering the type with:
The template doesn't have an explicit destructor, so it's wrong to use asOBJ_APP_CLASS_CD. Had it not been a template declaration the flag should have been CAK, since it has an explicit copy constructor and assignment operator, but for some reason the gnuc compiler ignores the existance of the copy constuctor and assignment operator so only asOBJ_APP_CLASS_C is the correct flag to use.
The asOBJ_APP_CLASS_ALLINTS will tell AngelScript that the object is composed entirely of integers so it will know how to pass the object by value on x64.
For dimension2df you should use asOBJ_APP_CLASS_ALLFLOATS, instead.
Regards,
Andreas
engine->RegisterObjectType("dimension2di", sizeof(dimension2di), asOBJ_VALUE | asOBJ_APP_CLASS_C | asOBJ_APP_CLASS_ALLINTS);
The template doesn't have an explicit destructor, so it's wrong to use asOBJ_APP_CLASS_CD. Had it not been a template declaration the flag should have been CAK, since it has an explicit copy constructor and assignment operator, but for some reason the gnuc compiler ignores the existance of the copy constuctor and assignment operator so only asOBJ_APP_CLASS_C is the correct flag to use.
The asOBJ_APP_CLASS_ALLINTS will tell AngelScript that the object is composed entirely of integers so it will know how to pass the object by value on x64.
For dimension2df you should use asOBJ_APP_CLASS_ALLFLOATS, instead.
Regards,
Andreas
AngelCode.com - game development and more - Reference DB - game developer references
AngelScript - free scripting library - BMFont - free bitmap font generator - Tower - free puzzle game
I tried this with just the use of asOBJ_APP_CLASS_C and with using both asOBJ_APP_CLASS_C and asOBJ_APP_CLASS_ALLINTS/asOBJ_APP_CLASS_ALLFLOATS but unfortunately in either case it is still getting the same crash
Hrm, I've been trying out some of our other bound methods on linux today and there is another one I've come across that gets the same error.
It involves another type provided by Irrlicht with similar binding code.
In case any of it contains useful info at all, I'll include the details here.
The type is a struct called Vec2f and you can see how it is bound here:
http://pastebin.com/zYhB5ztc
Its implementation is here:
http://pastebin.com/BXFjpeRR
This is an example of a class method that has this free error on linux/mac when executed:
[source lang="cpp"]engine->RegisterObjectMethod("CSpriteLayer", "void SetOffset( Vec2f o )",
asMETHOD( CSpriteLayer, SetOffset), asCALL_THISCALL);[/source]
This is an object method on the object type CSpriteLayer, registered this way:
[source lang="cpp"]engine->RegisterObjectType("CSpriteLayer", sizeof(CSpriteLayer), asOBJ_REF | asOBJ_NOCOUNT);[/source]
Example call:
[source lang="cpp"]arm.SetOffset( Vec2f(10.0f,-8.0f) );[/source]
It involves another type provided by Irrlicht with similar binding code.
In case any of it contains useful info at all, I'll include the details here.
The type is a struct called Vec2f and you can see how it is bound here:
http://pastebin.com/zYhB5ztc
Its implementation is here:
http://pastebin.com/BXFjpeRR
This is an example of a class method that has this free error on linux/mac when executed:
[source lang="cpp"]engine->RegisterObjectMethod("CSpriteLayer", "void SetOffset( Vec2f o )",
asMETHOD( CSpriteLayer, SetOffset), asCALL_THISCALL);[/source]
This is an object method on the object type CSpriteLayer, registered this way:
[source lang="cpp"]engine->RegisterObjectType("CSpriteLayer", sizeof(CSpriteLayer), asOBJ_REF | asOBJ_NOCOUNT);[/source]
Example call:
[source lang="cpp"]arm.SetOffset( Vec2f(10.0f,-8.0f) );[/source]
The Vec2f class doesn't have an explicit copy constructor, so it should be registered with asOBJ_APP_CLASS_CA, not asOBJ_APP_CLASS_CAK.
This will definitely make AngelScript invoke CallFree incorrectly for the Vec2f class.
I'm not sure about the dimension2d. But let's concentrate on the Vec2f type, since it is not a template type which should make it easier to understand.
This will definitely make AngelScript invoke CallFree incorrectly for the Vec2f class.
I'm not sure about the dimension2d. But let's concentrate on the Vec2f type, since it is not a template type which should make it easier to understand.
AngelCode.com - game development and more - Reference DB - game developer references
AngelScript - free scripting library - BMFont - free bitmap font generator - Tower - free puzzle game
I've tried the following on 32bit linux:
It is working successfully, without any crashes. Does it work on your setup too?
///////////////////////////////////
// This is the relevant part of the type from the Irrlicht engine.
// It is reproduced here to test the registration of the
// type with AngelScript.
template <class T>
class dimension2d
{
public:
dimension2d() : Width(0), Height(0) {}
dimension2d(const T& width, const T& height) :
Width(width), Height(height) {}
template <class U>
explicit dimension2d(const dimension2d<U>& other) :
Width((T)other.Width), Height((T)other.Height) { }
template <class U>
dimension2d<T>& operator=(const dimension2d<U>& other)
{
Width = (T) other.Width;
Height = (T) other.Height;
return *this;
}
dimension2d<T> operator+(const dimension2d<T>& other) const
{
return dimension2d<T>(Width+other.Width, Height+other.Height);
}
T Width;
T Height;
};
typedef dimension2d<float> dimension2df;
void Construct_dim2f(dimension2df *mem)
{
new(mem) dimension2df();
}
void Construct_dim2f(const dimension2df &other, dimension2df *mem)
{
new(mem) dimension2df(other);
}
void Construct_dim2f(float x, float y, dimension2df *mem)
{
new(mem) dimension2df(x, y);
}
void ByValue(dimension2df val)
{
assert( fabsf(val.Width - 1.0f) <= 0.0001f );
assert( fabsf(val.Height - 2.0f) <= 0.0001f );
}
bool TestIrrTypes()
{
bool fail = false;
int r;
COutStream out;
asIScriptEngine *engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);
engine->SetMessageCallback(asMETHOD(COutStream, Callback), &out, asCALL_THISCALL);
// The dimension2df type must be registered with asOBJ_APP_CLASS_C,
// despite it having an assignment and copy constructor. It must also
// be registered with asOBJ_APP_CLASS_FLOATS to work on Linux 64bit
r = engine->RegisterObjectType("dim2f", sizeof(dimension2df), asOBJ_VALUE | asOBJ_POD | asOBJ_APP_CLASS_C | asOBJ_APP_CLASS_ALLFLOATS); assert( r >= 0 );
r = engine->RegisterObjectBehaviour("dim2f",asBEHAVE_CONSTRUCT,"void f()", asFUNCTIONPR(Construct_dim2f, (dimension2df*), void), asCALL_CDECL_OBJLAST); assert( r >= 0 );
r = engine->RegisterObjectBehaviour("dim2f",asBEHAVE_CONSTRUCT,"void f(const dim2f &in)", asFUNCTIONPR(Construct_dim2f, (const dimension2df &, dimension2df*), void),asCALL_CDECL_OBJLAST); assert( r >= 0 );
r = engine->RegisterObjectBehaviour("dim2f",asBEHAVE_CONSTRUCT,"void f(float x, float y)", asFUNCTIONPR(Construct_dim2f, (float x, float y, dimension2df*), void),asCALL_CDECL_OBJLAST); assert( r >= 0 );
r = engine->RegisterObjectMethod("dim2f", "dim2f &opAssign(const dim2f &in)", asMETHODPR(dimension2df, operator =, (const dimension2df&), dimension2df&), asCALL_THISCALL); assert(r >= 0);
r = engine->RegisterObjectMethod("dim2f", "dim2f opAdd(const dim2f &in) const", asMETHODPR(dimension2df, operator+, (const dimension2df&) const, dimension2df), asCALL_THISCALL); assert( r >= 0 );
r = engine->RegisterObjectProperty("dim2f", "float x", asOFFSET(dimension2df, Width)); assert( r >= 0 );
r = engine->RegisterObjectProperty("dim2f", "float y", asOFFSET(dimension2df, Height)); assert( r >= 0 );
r = engine->RegisterGlobalFunction("void assert(bool)", asFUNCTION(Assert), asCALL_GENERIC); assert( r >= 0 );
r = engine->RegisterGlobalFunction("void ByValue(dim2f)", asFUNCTION(ByValue), asCALL_CDECL); assert( r >= 0 );
r = ExecuteString(engine, "dim2f video_res(800,600);\n"
"dim2f total_res;\n"
"total_res = video_res + video_res;\n"
"assert( total_res.x == 1600 && total_res.y == 1200 );\n"
"ByValue(dim2f(1,2)); \n");
if( r != asEXECUTION_FINISHED )
{
TEST_FAILED;
}
engine->Release();
return fail;
}
It is working successfully, without any crashes. Does it work on your setup too?
AngelCode.com - game development and more - Reference DB - game developer references
AngelScript - free scripting library - BMFont - free bitmap font generator - Tower - free puzzle game
Yes!!!
Thank you
I made changes so that our code matched yours and that worked.
Then I removed each change one by one and found that the culprits were the constructors. So by changing this line:
[source lang="cpp"]r = engine->RegisterObjectBehaviour(typeName, asBEHAVE_CONSTRUCT, "void f()",
asFUNCTIONPR(constructor<T>, (void*), void), asCALL_CDECL_OBJLAST);[/source]
To the following, fixed it:
[source lang="cpp"]r = engine->RegisterObjectBehaviour("dimension2df", asBEHAVE_CONSTRUCT,"void f()",
asFUNCTIONPR(Construct_dim2f, (dimension2df*), void), asCALL_CDECL_OBJLAST);[/source]
I'm a little confused why that fixed it but I'm certainly pleased that it did
Gonna take a look at Vec2f now. Perhaps there is the same problem there (changed to asOBJ_APP_CLASS_CA with no improvement).
Thank you
I made changes so that our code matched yours and that worked.
Then I removed each change one by one and found that the culprits were the constructors. So by changing this line:
[source lang="cpp"]r = engine->RegisterObjectBehaviour(typeName, asBEHAVE_CONSTRUCT, "void f()",
asFUNCTIONPR(constructor<T>, (void*), void), asCALL_CDECL_OBJLAST);[/source]
To the following, fixed it:
[source lang="cpp"]r = engine->RegisterObjectBehaviour("dimension2df", asBEHAVE_CONSTRUCT,"void f()",
asFUNCTIONPR(Construct_dim2f, (dimension2df*), void), asCALL_CDECL_OBJLAST);[/source]
I'm a little confused why that fixed it but I'm certainly pleased that it did
Gonna take a look at Vec2f now. Perhaps there is the same problem there (changed to asOBJ_APP_CLASS_CA with no improvement).
It was the same
I'm really not sure why the bindings for Vec2f were written as if it were a template, but once I changed it to bind to non-template constructor methods the crashes went away.
So it seems there is a problem with using template constructors on linux/mac.
Thank you so much for your help!
I'm really not sure why the bindings for Vec2f were written as if it were a template, but once I changed it to bind to non-template constructor methods the crashes went away.
So it seems there is a problem with using template constructors on linux/mac.
Thank you so much for your help!
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement