Jump to content
  • Advertisement
Sign in to follow this  
saejox

Is this a memory leak ? (CScriptArray)

This topic is 2293 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 create a CScriptArray in engine and return it to script like this

Function registration is this,

r = engine->RegisterObjectMethod("DataFile", "array<string>@ GetValuesOfChildrenWithName(const string &in, const string &in)", asMETHOD(DataFile, GetValuesOfChildrenWithName), asCALL_THISCALL);assert( r >= 0 );


GetValuesOfChildrenWithName function in C++
(horrible function naming smile.png it gets values of children nodes with the given name)

CScriptArray *DataFile::GetValuesOfChildrenWithName(const string &location, const string &name)
{
std::vector<string> allvalues;
ptree &tree = pt.get_child(location);
BOOST_FOREACH(boost::property_tree::ptree::value_type &v, tree)
{
if(v.first == name )
{
allvalues.push_back(v.second.get_value<string>());
}
}

asIObjectType* t = ScriptManager::getSingletonPtr()->engine->GetObjectTypeById(ScriptManager::getSingletonPtr()->engine->GetTypeIdByDecl("array<string>"));

CScriptArray* arr = new CScriptArray(allvalues.size(), t); // i do not Add Ref, since i dont need this array in C++
;

for (unsigned int i = 0; i< allvalues.size() ; ++i)
{
arr->InsertAt(i, new string(allvalues)); // this works, but would it cause a memory leak ?
}

return arr;
}


Script function,
called about 600 times a second.

void Routine()
{
DataFile @df = DFM.GetDataFile("../../gamedata/newfile.xml");

array<string> arr = df.GetValuesOfChildrenWithName("Root", "SomeNode");

for( uint n = 0; n < arr.length; n++ )
{
//nothing happens here, for now.
}
}


here is DFM.GetDataFile function, in case you suspect it

DataFile * DataFileManager::GetDataFile( const string &filename )
{
if(!dataFiles.count(filename))
{
return 0;
}

return &dataFiles[filename];
}


DataFile is a asOBJ_REF | asOBJ_NOCOUNT type.

I don't have any leak detector programs at the moment, but program's memory usage is increasing at a rapid rate.

Is there a better way to send an array to script?
if not, What did i do wrong?

thank you. Edited by saejox

Share this post


Link to post
Share on other sites
Advertisement
Is this line how it's written in the script?
array<string> arr = df.GetValuesOfChildrenWithName("Root", "SomeNode");

Without an @ on array<string>, you'll be copying the array each time the code is executed. If you aren't manually running a full cycle on the garbage collector, that could take a very long time to clean up.

Share this post


Link to post
Share on other sites

Is this line how it's written in the script?
array<string> arr = df.GetValuesOfChildrenWithName("Root", "SomeNode");

Without an @ on array<string>, you'll be copying the array each time the code is executed. If you aren't manually running a full cycle on the garbage collector, that could take a very long time to clean up.




array<string> arr = df.GetValuesOfChildrenWithName("Root", "SomeNode");

and

array<string> @arr = df.GetValuesOfChildrenWithName("Root", "SomeNode");


both yield the same result. memory keeps expanding.

i also call this every frame

engine->GarbageCollect(asGC_FULL_CYCLE);

just to test if the garbage collector is slow to catch up.

i doesn't matter. memory keeps expanding. Edited by saejox

Share this post


Link to post
Share on other sites

CScriptArray* arr = new CScriptArray(6, t);

for (unsigned int i = 0; i< 6 ; ++i)
{
arr->InsertAt(i, new string(allvalues));
}



code above creates an array with 12 elements. i dont get why.
fixed it like this. (this is not the cause of the leak !)


CScriptArray* arr = new CScriptArray(0, t);
for (unsigned int i = 0; i< 6 ; ++i)
{
arr->InsertLast(new string(allvalues));
}


Anyway, memory leak still there.

Also
http://www.angelcode...ddon_array.html
example has a CScriptString. which doesnt exist anymore afaik.

i use scriptstdstring addon for std::string. Edited by saejox

Share this post


Link to post
Share on other sites
The memory leak is because you allocate a new string when passing the argument to the InsertAt/InsertLast. InsertAt/InsertLast will make a copy of the value, so you should be passing a pointer to the original value.

You're first example created 12 elements, because you created the array with the initial size of 6 elements, then inserted 6 more elements.

The correct implementation is:



// Create the array with the known length
CScriptArray* arr = new CScriptArray(6, t);
for (unsigned int i = 0; i< 6 ; ++i)
{
// Set the value of each element
arr->SetValue(i, &allvalues);
}


InsertAt or InsertLast would also work if used correctly, but it would be slower as the array would have to be resized with each new element added.

Thanks for pointing out the use of CScriptString in the manual. You're correct that the CScriptString is no longer an official add-on, so it shouldn't be used as the example. I'll fix this for the next update.

Regards,
Andreas

Share this post


Link to post
Share on other sites
thank you. that was it.

also, SetValue is a protected method. Is this intended or just an oversight?

Share this post


Link to post
Share on other sites
Originally it was meant to be an internal method, but as it is now it is safe to be used from the application. I'll update it to make it a public method.

Thanks.

[edit] Done in revision 1300. Edited by Andreas Jonsson

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!