Jump to content
  • Advertisement
Sign in to follow this  
saejox

CScriptAny and [ ] operator, Questions about ref counting

This topic is 2265 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,

after learning that i cant pass objects as pure pointers, i chose to use any ad-don.

i have an hashmap implementation like this,


r = engine->RegisterObjectType("hashmap2D", sizeof(hashmap2D), asOBJ_VALUE | asOBJ_APP_CLASS_C); assert( r >= 0 );

r = engine->RegisterObjectMethod("hashmap2D", "any @opIndex(const Vector2 &in)", asFUNCTION(hashmap2D::hashmap2DopIndex), asCALL_CDECL_OBJLAST) ; assert( r >= 0 );

r = engine->RegisterObjectMethod("hashmap2D", "any @Get(const Vector2 &in)", asMETHOD(hashmap2D, Get), asCALL_THISCALL); assert( r >= 0 );

r = engine->RegisterObjectMethod("hashmap2D", "void Set(const Vector2 &in, any @value)", asMETHOD(hashmap2D, Set), asCALL_THISCALL); assert( r >= 0 );




Destructor of hashmap2D is this. it calls release on all any objects

// this is called only once. when engine->Release(); called
for(Hash2D::iterator it = values.begin(); it != values.end();)
{
it->second->Release(); // refCount is -17891602, any is already destroyed, but why?
it = values.erase(it);
}


Set function

void Set(const Vector2 &pos, CScriptAny *obj)
{
obj->AddRef(); // addRef since i am storing it
values[pos] = obj;
}


get function

CScriptAny *Get(const Vector2 &pos)
{
if(!values.count(pos))
return 0;

return values[pos];
}



[ ] implemented like this

static CScriptAny * hashmap2DopIndex(const Vector2 &index, hashmap2D *self)
{
if( self->values.count(index) )
{
return self->values.at(index);
}
return 0;
}


script function calling [ ] operator is this


hashmap2D map; // global

void SomeFunc()
{
Vector2 pos(1,1);
any coord;
coord.store(Vector2(54, 84));
//refCount of any is 3
map.Set(pos, coord);
//refCount of any is 4 ( me + GC + SomeFunc + ?? ) // who owns 4th ref?

any coord2;
//refCount of any is 4
coord2 = map.Get(pos);
//refCount of any is 4
Vector2 stored;
coord2.retrieve(stored);

Vector2 v;
//refCount of any is 3, ???? why did it decrease?
any va = map[pos];
//refCount of any is 3
va.retrieve(v);
ConsoleOutput("Stored vector x: " + v.x + " y: " + v.y); // value accessed correctly
}



During program termition, it ends with a Heap corruption.
it seems i am over destroying it, but hashmap2D destructor is called only once.

it does not cause heap when i just call only [ ] or only Get. it does crash when i call both.

i am very confused on how hashmap2D is destroyed.
i hope i made the issue clear enough.

thank you. Edited by saejox

Share this post


Link to post
Share on other sites
Advertisement
When you receive a handle, it has already been grabbed. When you return a handle, it needs to be grabbed before being returned. If you use auto-handles ( @+ instead of @ ), your current code should work, but will be a bit slower than doing it yourself.

Share this post


Link to post
Share on other sites

When you receive a handle, it has already been grabbed. When you return a handle, it needs to be grabbed before being returned. If you use auto-handles ( @+ instead of @ ), your current code should work, but will be a bit slower than doing it yourself.


as understand it Get and [] calls here decreases ref count of the any object.
i need to register them as "any @+opIndex " and "any @+Get"

this works.
but so does calling AddRef at each Get and [ ] calls. i will call AddRef since you said @+ is slower.
problem solved :) thank you

i have a little questions tho,

what's the diffrence between
any @coord2; @coord2 = map.Get(pos); // coord2 is a handle?
and
any coord2;coord2 = map.Get(pos); // coord2 is a value copied from @Get?, if so why do i have to increase its reference
?

is it same since any is asOBJ_REF?

Share this post


Link to post
Share on other sites
It seems you already got your answer, but just in case it is still not clear:


Your Set() method should not call AddRef(). If it didn't store the handle, it should call Release().

Your Get() and opIndex() methods should call AddRef() before returning the handle.


@+ in the parameter lists will tell AngelScript to automatically release the handle after the function returns. So if you use this when registering your Set() method, then you don't need to change the code.

@+ in the return value will tell AngelScript to automatically call AddRef on the returned handle after the function returns. If you use it with your Get() and opIndex() methods you also do not need to change the code.

This is detailed in the manual.


With your last question: map.Get(pos) still returns a handle to the any object that will be released by AngelScript after it has been value copied to the local variable. That is why you have to increase its reference.

Regards,
Andreas

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!