Crash on exit (binding wrong?)

Started by
6 comments, last by WitchLord 10 years, 7 months ago

Hey, I'm experiencing a crash in free() on exit. I'm lost, so maybe you can tell me if I did something wrong in the bindings?


struct Tile
{
    b2Fixture* edgeN, *edgeS, *edgeW, *edgeE;
    u16 blobid1, blobid2;
    u16 backblobid1, backblobid2;
    TileType type;
	u16 flags;
    u8 support;
    u8 dirt;
    u8 light;
    u8 noise;
    u8 damage;

	Tile();
	Tile( const TileType t );
	Tile( Tile& t );

	Tile& operator=(const Tile& t) 
	{ 
		type = t.type;
		support = t.support;
		dirt = t.dirt;
		light = t.light;
		flags = t.flags;
		noise = t.noise;
		damage = t.damage;
		return *this;
	}	

	bool operator==(const Tile& rhs)
	{
		return (type == rhs.type);	  // legacy
	}	
	bool operator==(const Tile& rhs) const
	{
		return (type == rhs.type);	  // legacy
	}	

	enum TileFlags {
		SPARE_0 = 0x01,
		BACKGROUND = 0x02,
		SOLID = 0x04,
		LADDER = 0x08,
		LIGHT_PASSES = 0x10,
		WATER_PASSES = 0x20,
		FLAMMABLE = 0x40,
		PLATFORM = 0x80,
		LIGHT_SOURCE = 0x100,
		MIRROR = 0x200,
		FLIP = 0x400,
		ROTATE = 0x800,
		SPARE_1 = 0x1000,
		SPARE_2 = 0x2000,
		SPARE_3 = 0x4000,
		SPARE_4 = 0x8000
	};
};

The binding:


    r = engine->RegisterObjectType("Tile", sizeof(Tile), asOBJ_VALUE | asOBJ_POD | asOBJ_APP_CLASS_CA); assert(r >= 0);
    // Set Vec2f behaviour.
    // Initialisation and deinitialisation
    r = engine->RegisterObjectBehaviour("Tile", asBEHAVE_CONSTRUCT, "void f()", asFUNCTIONPR(constructorTile,
                                        (void*), void), asCALL_CDECL_OBJLAST); assert(r >= 0);
    r = engine->RegisterObjectBehaviour("Tile", asBEHAVE_DESTRUCT, "void f()", asFUNCTION(deconstructorTile),
                                        asCALL_CDECL_OBJLAST); assert(r >= 0);

	r = engine->RegisterObjectProperty("Tile", "TileType type", asOFFSET(Tile, type)); assert(r >= 0);
	r = engine->RegisterObjectProperty("Tile", "u8 support", asOFFSET(Tile, support)); assert(r >= 0);
	r = engine->RegisterObjectProperty("Tile", "u8 dirt", asOFFSET(Tile, dirt)); assert(r >= 0);
	r = engine->RegisterObjectProperty("Tile", "u8 light", asOFFSET(Tile, light)); assert(r >= 0);
	r = engine->RegisterObjectProperty("Tile", "u16 flags", asOFFSET(Tile, flags)); assert(r >= 0);
	r = engine->RegisterObjectProperty("Tile", "u8 damage", asOFFSET(Tile, damage)); assert(r >= 0);
	r = engine->RegisterObjectProperty("Tile", "u8 noise", asOFFSET(Tile, noise)); assert(r >= 0);
	r = engine->RegisterObjectProperty("Tile", "u16 blobid1", asOFFSET(Tile, blobid1)); assert(r >= 0);
	r = engine->RegisterObjectProperty("Tile", "u16 blobid2", asOFFSET(Tile, blobid2)); assert(r >= 0);
	r = engine->RegisterObjectProperty("Tile", "u16 backblobid1", asOFFSET(Tile, backblobid1)); assert(r >= 0);
	r = engine->RegisterObjectProperty("Tile", "u16 backblobid2", asOFFSET(Tile, backblobid2)); assert(r >= 0);
	r = engine->RegisterObjectMethod("Tile", "Tile& opAssign(const Tile &in)",
		asMETHODPR(Tile, operator=, (const Tile&), Tile&),
		asCALL_THISCALL); assert(r >= 0);

	r = engine->SetDefaultNamespace("Tile"); assert( r >= 0 );
	r = engine->RegisterEnum("TileFlags"); assert( r >= 0 );
	r = engine->RegisterEnumValue("TileFlags", "SPARE_0", Tile::SPARE_0); assert( r >= 0 );
	r = engine->RegisterEnumValue("TileFlags", "SOLID", Tile::SOLID); assert( r >= 0 );
	r = engine->RegisterEnumValue("TileFlags", "BACKGROUND", Tile::BACKGROUND); assert( r >= 0 );
	r = engine->RegisterEnumValue("TileFlags", "LADDER", Tile::LADDER); assert( r >= 0 );
	r = engine->RegisterEnumValue("TileFlags", "LIGHT_PASSES", Tile::LIGHT_PASSES); assert( r >= 0 );
	r = engine->RegisterEnumValue("TileFlags", "WATER_PASSES", Tile::WATER_PASSES); assert( r >= 0 );
	r = engine->RegisterEnumValue("TileFlags", "FLAMMABLE", Tile::FLAMMABLE); assert( r >= 0 );
	r = engine->RegisterEnumValue("TileFlags", "PLATFORM", Tile::PLATFORM); assert( r >= 0 );
	r = engine->RegisterEnumValue("TileFlags", "LIGHT_SOURCE", Tile::LIGHT_SOURCE); assert( r >= 0 );
	r = engine->RegisterEnumValue("TileFlags", "MIRROR", Tile::MIRROR); assert( r >= 0 );
	r = engine->RegisterEnumValue("TileFlags", "FLIP", Tile::FLIP); assert( r >= 0 );
	r = engine->RegisterEnumValue("TileFlags", "ROTATE", Tile::ROTATE); assert( r >= 0 );
	r = engine->RegisterEnumValue("TileFlags", "SPARE_1", Tile::SPARE_1); assert( r >= 0 );
	r = engine->RegisterEnumValue("TileFlags", "SPARE_2", Tile::SPARE_2); assert( r >= 0 );
	r = engine->RegisterEnumValue("TileFlags", "SPARE_3", Tile::SPARE_3); assert( r >= 0 );
	r = engine->RegisterEnumValue("TileFlags", "SPARE_4", Tile::SPARE_4); assert( r >= 0 );
	r = engine->SetDefaultNamespace(""); assert( r >= 0 );

And some functions that use it:


    r = engine->RegisterObjectMethod("CMap", "void server_SetTile(Vec2f pos, const Tile &in tile)",
                                     asMETHODPR( CMap, server_SetTile, (Vec2f, const Tile&), void),
                                     asCALL_THISCALL); assert(r >= 0);

    r = engine->RegisterObjectMethod("CMap", "Tile getTile( Vec2f pos ) const",
                                     asMETHODPR( CMap, getTile, (Vec2f) const, Tile),
                                     asCALL_THISCALL); assert(r >= 0);
    r = engine->RegisterObjectMethod("CMap", "Tile getTileFromTileSpace( Vec2f pos ) const",
                                     asMETHODPR( CMap, getTile_Vec2f, (Vec2f) const, Tile),
                                     asCALL_THISCALL); assert(r >= 0);
    r = engine->RegisterObjectMethod("CMap", "Tile getTile( u32 offset ) const",
                                     asMETHODPR( CMap, getTile, (u32) const, Tile),
                                     asCALL_THISCALL); assert(r >= 0);
KAG DEVLOG: http://kagdev.tumblr.com/
Advertisement

What version of AngelScript are you using now? On which platform does the crash happen? Does it matter?

The only thing I see that could potentially be wrong is that it appears that your Tile class has a copy constructor, which means it should be registered with the flag asOBJ_APP_CLASS_CAK. On gnuc based compilers the existance of the copy constructor influences how the object is passed by value to/from the application (though with the size of the Tile class I don't think it should matter).

Does the crash only happen after calling one of the functions that take or return the Tile type?

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

Visual Studio 2010

Angelscript 2.26.2

The crash happens on next map (after resources are freed, and only in the release mode). I'm not sure now this is the reason for the crash, so lets leave it.

However I have a memory leak (might be related) and I need some help figuring out what causes this.

The leak happens on every single script in the game. What do you think it is leaking ?


 d:\transhuman\kag\3rd\angelscript\sdk\angelscript\source\as_builder.cpp (3529): (Module name unavailable)!asCBuilder::GetParsedFunctionDetails + 0x14 bytes
    d:\transhuman\kag\3rd\angelscript\sdk\angelscript\source\as_builder.cpp (3595): (Module name unavailable)!asCBuilder::RegisterScriptFunctionFromNode
    d:\transhuman\kag\3rd\angelscript\sdk\angelscript\source\as_builder.cpp (658): (Module name unavailable)!asCBuilder::RegisterNonTypesFromScript + 0x1E bytes
    d:\transhuman\kag\3rd\angelscript\sdk\angelscript\source\as_builder.cpp (569): (Module name unavailable)!asCBuilder::ParseScripts
    d:\transhuman\kag\3rd\angelscript\sdk\angelscript\source\as_builder.cpp (231): (Module name unavailable)!asCBuilder::Build
    d:\transhuman\kag\3rd\angelscript\sdk\angelscript\source\as_module.cpp (222): (Module name unavailable)!asCModule::Build + 0xB bytes
    d:\transhuman\kag\trunk\scripting\angelscript\add_on\scriptbuilder\scriptbuilder.cpp (651): (Module name unavailable)!CScriptBuilder::Build + 0x17 bytes
    d:\transhuman\kag\trunk\scripting\angelscript\add_on\scriptbuilder\scriptbuilder.cpp (143): (Module name unavailable)!CScriptBuilder::BuildModule
    d:\transhuman\kag\trunk\scripting\asscript.cpp (201): (Module name unavailable)!asScript::loadScript + 0xB bytes
    d:\transhuman\kag\trunk\scripting\asscriptmanager.cpp (371): (Module name 
KAG DEVLOG: http://kagdev.tumblr.com/

Version 2.27.0 had a bug fix that may be related to the crash you're seeing. The bug was that AngelScript didn't allocate enough space for value types if the size of the type was not evenly divisable with 4. What is the size of the Tile structure?

Would it be possible to upgrade to the latest release of AngelScript (2.27.1) to see if the problem goes away?

I'm not sure about the memory leak. Have you tried turning on MSVC memory debug routines to identify the memory that is being leaked?

#include <crtdbg.h>
 
// In the main function
_CrtSetDbgFlag(_CRTDBG_LEAK_CHECK_DF|_CRTDBG_ALLOC_MEM_DF);
_CrtSetReportMode(_CRT_ASSERT,_CRTDBG_MODE_FILE);
_CrtSetReportFile(_CRT_ASSERT,_CRTDBG_FILE_STDERR);
 
// Use _CrtSetBreakAlloc(n) to find a specific memory leak
_CrtSetBreakAlloc(924);

If you can run the application on Linux I recommend using valgrind to find any memory problems. It will detect not only leaks but also writing to or reading from unallocated memory.

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

Will upgrade to the latest Angelscript cause that sounds like it might be it.

I use Visual Leak Detector and that was its output.

Will report back.

KAG DEVLOG: http://kagdev.tumblr.com/

The crash was unrelated.

Thanks for the CRT tip.

Visual Leak Detector is very good too.

KAG DEVLOG: http://kagdev.tumblr.com/

Does this mean that the only problem you're having now is the memory leak?

I reviewed the code in asCBuilder::GetParsedFunctionDetails that Visual Leak Detector showed as the offending leak, and I identified a potential for memory leaks if there are errors in the script, e.g. a name conflict on a function with default arguments. I'll have that fixed as soon as possible.

Are you seeing memory leaks even when there are no compiler errors?

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

It turns out it didn't require a compiler error to hit the memory leak. Any shared functions with default arguments would leak in the second and following modules they were compiled in.

I've fixed this leak in revision 1719.

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

This topic is closed to new replies.

Advertisement