Jump to content
  • Advertisement
Sign in to follow this  
cvet

Array not released

This topic is 1334 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

AngelScript revision 1996.

 

Array (at least, not check other types) not released and as result I have leaked arrays and stored pointers in it.

Script
void main()
{
  mytype@[] a;
  myfunc(a);
}

Native
RegisterGlobalFunction( "void myfunc(mytype@[]@+ a)" )
ScriptArray* b = 0;
void myfunc(ScriptArray* a)
{
  // 'a' have refCount == 3 at input, this is correct?
  if (!b)
  {
    b = a;
    b->AddRef();
  }
}
Then I skip few frames and in 'b' I see always 2 (in debugger), not 1 as expected.
Please check this moment.

Share this post


Link to post
Share on other sites
Advertisement

If 'myType' needs to be garbage collected, or might need to be garbage collected (not sure of the exact logic for arrays), the array will also be garbage collected. The GC will hold a reference to whatever was added to it until the GC decides it can be deleted.

Share this post


Link to post
Share on other sites

ThyReaper has the right of it.

 

The VM notifies the GC about the array instance at creation (counts for 1 reference) since it can potentially be involved in a circular reference (e.g. array -> mytype -> array, or array -> type derived from mytype -> array).

 

This is why it has a refcount of 3 when you inspect the object at the entry of the myfunc() call. 1 is held by the garbage collector, 1 is held by the local variable in the script, and 1 is the reference being passed into the myfunc().

Share this post


Link to post
Share on other sites

Yes, this is true, I was forgot about GC.

Then there another bug - asBEHAVE_RELEASEREFS not invoked, because objects in array not released, also I set breakpoint in ReleaseAllHandles and debugger not stop on it.

Share this post


Link to post
Share on other sites

The GC only calls ReleaseAllHandles() if it detects a circular reference, which is not the case here.

 

The GC will hold on to its reference of the object until all other references have been released. You're storing a reference in the variable ScriptArray *b and calling AddRef(). Until you call Release() to release that reference, the GC must not release its reference either.

Share this post


Link to post
Share on other sites

This is just example, here another to describe last bug

Script

void main()
{
  mytype@[] a;
  myfunc(a);
}

Native

mytype* b = new mytype();

void myfunc(ScriptArray* a)
{
  a->Resize(1);

  a->SetValue(0, (void*)&b);
}

Here ReleaseAllHandles must invoked or not?

Share this post


Link to post
Share on other sites

In dovumentation I see this

...ReleaseAllReferences

// When we receive this call, we are as good as dead, but
// the garbage collector will still hold a references to us, so we
// cannot just delete ourself yet. Just free all references to other
// objects that we hold

By this description ReleaseAllReferences must call in my situation. Isn't it?

Share this post


Link to post
Share on other sites

In any way, even ReleaseAllReferences not used for this, array object can contain objects not managed by GC and it prevent their releasing until GC not release array.

Share this post


Link to post
Share on other sites

No, ReleaseAllReferences will not be called in this second example either. ReleaseAllReferences is only called if a circular reference is detected that has to be broken by the garbage collector in order to be able to release the objects.

 

You have this code in your second example:

 

mytype* b = new mytype();  // I assume this is a global variable. Where are you releasing the reference created by the constructor?
void myfunc(ScriptArray* a) // I assume you've registered the function as "void myfunc(array<mytype@>[]@+)" as in your first example
{
  a->Resize(1);
  a->SetValue(0, (void*)&b);  // This will increment the refcount to the mytype so that it is now 2
}

 

After the function call the array will go out of scope and will be released. As no other references to the array exists, the garbage collector will also release its reference, and thus the array will be destroyed which will in turn release the reference to mytype.

 

However, even after the array is destroyed, your application is still holding on to a reference to mytype which is why it is not destroyed.

Share this post


Link to post
Share on other sites

 

After the function call the array will go out of scope and will be released. As no other references to the array exists, the garbage collector will also release its reference, and thus the array will be destroyed which will in turn release the reference to mytype.

If I disable automatic garbage collection and will not call GC explicitly then array not will be released and all handles in it too.

 

However, even after the array is destroyed, your application is still holding on to a reference to mytype which is why it is not destroyed.

I do not say about destroying, I say about releasing. Because in mytype used 'short' for refCount and I have overflow after some time if GC not invoked (myfunc is called every frame).

If you say this is normal behaviour that GC objects can hold not GC objects before GC kill it, then it's ok, I just want point on this behaviour.

Edited by cvet

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.

Participate in the game development conversation and more when you create an account on GameDev.net!

Sign me up!