Advertisement

Is this a memory leak ? (CScriptArray)

Started by May 07, 2012 09:05 PM
5 comments, last by WitchLord 12 years, 6 months ago
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.
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.
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.




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.

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.
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

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

thank you. that was it.

also, SetValue is a protected method. Is this intended or just an oversight?
Advertisement
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.

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