YetAnotherForum
Welcome Guest Search | Active Topics | Log In | Register

squirrel engine leaks again
marius
#1 Posted : Saturday, February 25, 2012 5:31:25 PM(UTC)
Rank: Member

Groups: Registered
Joined: 10/18/2010(UTC)
Posts: 14
Location: Canada

Thanks: 0 times
Was thanked: 1 time(s) in 1 post(s)
Hi,

The previous post regarding the leak is over bloated and is hard to follow.

Here is a CodeBlocks project for Linux which proves the point.

Test Program
sqtest.tar.gz

Memory monitor script.
mu.sh

Sq Test Code Excerpt:

Code:
#include <iostream>
#include "sqwrap.h"
using namespace std;
void test();
int main(){
    test();
    return 0;
}

const char* program = ""
"function main(){"
"    local k;"
"for(k=0; k< 100; k++)"
"        print(k);"
"}"
"main()";

void test()
{
    SqEnv env;
    MyScript s = env.CompileBuffer(program); //leaks less
    for(int k=0;k<100;k++){
        for(int i=0;i<10000;i++){
            try{
                /// MyScript s = env.CompileBuffer(program); leaks more
                s.Run();   // each time is loosing a CLOSURE*
            }catch(Sqrat::Exception& e){
                std::cout << e.Message();
            }
            usleep(10000);
        }
        sleep(1);
        std::cout << "next chunk\n";
    }
}



results:

VM: 14552, RSS: 1644 THRDS: 1 PROCS:1 TOTAL: 1 CPU%: 43
VM: 14552, RSS: 1644 THRDS: 1 PROCS:1 TOTAL: 1 CPU%: 28
VM: 14696, RSS: 1904 THRDS: 1 PROCS:1 TOTAL: 1 CPU%: 41
VM: 14740, RSS: 1904 THRDS: 1 PROCS:1 TOTAL: 1 CPU%: 38
VM: 14788, RSS: 1904 THRDS: 1 PROCS:1 TOTAL: 1 CPU%: 39
VM: 14836, RSS: 1904 THRDS: 1 PROCS:1 TOTAL: 1 CPU%: 39
VM: 14884, RSS: 2080 THRDS: 1 PROCS:1 TOTAL: 1 CPU%: 41

or:

vm.Run()
>>>>stack dump<<<<
IP: 0x1000001
prev stack base: 0
prev top: 0
>[0]:TABLE 0x665700[(nil)]
[1]:CLOSURE [0x667270]
[2]:CLOSURE [0x667270]
vm.Run()
>>>>stack dump<<<<
IP: 0x1000001
prev stack base: 0
prev top: 0
>[0]:TABLE 0x665700[(nil)]
[1]:CLOSURE [0x667270]
[2]:CLOSURE [0x667270]
[3]:CLOSURE [0x667270]
vm.Run()
>>>>stack dump<<<<
IP: 0x1000001
prev stack base: 0
prev top: 0
>[0]:TABLE 0x665700[(nil)]
[1]:CLOSURE [0x667270]
[2]:CLOSURE [0x667270]
[3]:CLOSURE [0x667270]
[4]:CLOSURE [0x667270]
marius
#2 Posted : Sunday, February 26, 2012 7:16:02 AM(UTC)
Rank: Member

Groups: Registered
Joined: 10/18/2010(UTC)
Posts: 14
Location: Canada

Thanks: 0 times
Was thanked: 1 time(s) in 1 post(s)
Memory leak fixed

I fix it in above 'way 'of managing lifetime of the objects.

-use pop() in ~MyScript d-tor
-use Run2 taken from sqplus

The stack has to be popped b'cause compile returns in the
closure 2 the compiled. In sqrat 'way' where the Script class
allows re-entrance as: s.compile() s.run() would be a
little more difficult to manage, but this is the idea.

Fixed code:

Code:

try{
    MyScript s = env.CompileBuffer(program);
    s.Run2();                      <----- FIX
    //env.vm()->dumpstackb();
    }catch(Sqrat::Exception& e){
         std::cout << e.Message();
}

...

MyScript::~MyScript()
{
     ...
     sq_pop(_vm,1); <---- FIX
}

  bool MyScript::Run2()  <---- FIX (from SqPLus)
    {
        Sqrat::DefaultVM::Set(_vm);
        sq_pushobject(_vm,_obj);
        sq_pushroottable(_vm);
        if(SQ_SUCCEEDED(sq_call(_vm,1,true,true/*we need a return value*/)))
        {
            SQObject obj;
            sq_getstackobj(_vm,-1,&obj);
            sq_pop(_vm,2);
            return true;
        }
        sq_pop(_vm,1);
        throw Sqrat::Exception(Sqrat::LastErrorString(_vm));
        return false;//never reached
    }



Marius C.
1 user thanked marius for this useful post.
atai on 3/18/2012(UTC)
atai
#3 Posted : Saturday, March 31, 2012 7:15:57 AM(UTC)
Rank: Advanced Member

Groups: Registered
Joined: 8/16/2005(UTC)
Posts: 288

Thanks: 14 times
Was thanked: 13 time(s) in 11 post(s)
committed to SVN for Sqrat a fix that maintains strong references from the Script class.
Using dumpstack() in SQVM of Squirrel shows the stack is no longer leaking after Script::Compile...() and Script::Run()

I hope people using Sqrat can test the latest version to make sure the leak is fixed.
atai
#4 Posted : Saturday, March 31, 2012 7:18:09 AM(UTC)
Rank: Advanced Member

Groups: Registered
Joined: 8/16/2005(UTC)
Posts: 288

Thanks: 14 times
Was thanked: 13 time(s) in 11 post(s)
atai wrote:
committed to SVN for Sqrat a fix that maintains strong references from the Script class.
Using dumpstack() in SQVM of Squirrel shows the stack is no longer leaking after Script::Compile...() and Script::Run()

I hope people using Sqrat can test the latest version to make sure the leak is fixed.


the key change is in the file sqratScript.h, the key part of the current version also listed below
Code:

namespace Sqrat {

class Script : public Object {
public:
    Script(HSQUIRRELVM v = DefaultVM::Get()) : Object(v, false) {
    }

    ~Script()
    {
        if(!sq_isnull(obj)) {
            sq_release(vm, &obj);
        }
    }
    void CompileString(const string& script) {
        if(!sq_isnull(obj)) {
            sq_release(vm, &obj);
        }
        if(SQ_FAILED(sq_compilebuffer(vm, script.c_str(), static_cast<SQInteger>(script.size() * sizeof(SQChar)), _SC(""), true))) {
            throw Exception(LastErrorString(vm));
        }
        sq_getstackobj(vm,-1,&obj);
        sq_addref(vm, &obj);
        sq_pop(vm, 1);
    }
   
    bool CompileString(const string& script, string& errMsg) {
        if(!sq_isnull(obj)) {
            sq_release(vm, &obj);
        }
        if(SQ_FAILED(sq_compilebuffer(vm, script.c_str(), static_cast<SQInteger>(script.size() * sizeof(SQChar)), _SC(""), true))) {
            errMsg = LastErrorString(vm);
            return false;
        }
        sq_getstackobj(vm,-1,&obj);
        sq_addref(vm, &obj);
        sq_pop(vm, 1);
        return true;
    }

    void CompileFile(const string& path) {
        if(!sq_isnull(obj)) {
            sq_release(vm, &obj);
        }
        if(SQ_FAILED(sqstd_loadfile(vm, path.c_str(), true))) {
            throw Exception(LastErrorString(vm));
        }
        sq_getstackobj(vm,-1,&obj);
        sq_addref(vm, &obj);
        sq_pop(vm, 1);
    }

    bool CompileFile(const string& path, string& errMsg) {
        if(!sq_isnull(obj)) {
            sq_release(vm, &obj);
        }
        if(SQ_FAILED(sqstd_loadfile(vm, path.c_str(), true))) {
            errMsg = LastErrorString(vm);
            return false;
        }
        sq_getstackobj(vm,-1,&obj);
        sq_addref(vm, &obj);
        sq_pop(vm, 1);
        return true;
    }

    void Run() {
        if(!sq_isnull(obj)) {
            SQRESULT result;
            sq_pushobject(vm, obj);
            sq_pushroottable(vm);
            result = sq_call(vm, 1, false, true);
            sq_pop(vm, 1);
            if(SQ_FAILED(result)) {
                throw Exception(LastErrorString(vm));
            }
        }
    }

    bool Run(string& errMsg) {
        if(!sq_isnull(obj)) {
            SQRESULT result;
            sq_pushobject(vm, obj);
            sq_pushroottable(vm);
            result = sq_call(vm, 1, false, true);
            sq_pop(vm, 1);
            if(SQ_FAILED(result)) {
                errMsg = LastErrorString(vm);
                return false;
            }
        }
        return true;
    }


    void WriteCompiledFile(const string& path) {
        if(!sq_isnull(obj)) {
            sq_pushobject(vm, obj);
            sqstd_writeclosuretofile(vm, path.c_str());
            //sq_pop(vm, 1);  // needed?
        }
    }
};
}




Please let me know if you see any issues
Users browsing this topic
Guest
Forum Jump  
You cannot post new topics in this forum.
You cannot reply to topics in this forum.
You cannot delete your posts in this forum.
You cannot edit your posts in this forum.
You cannot create polls in this forum.
You cannot vote in polls in this forum.

Clean Slate theme by Jaben Cargman (Tiny Gecko)
Powered by YAF 1.9.4 | YAF © 2003-2010, Yet Another Forum.NET
This page was generated in 0.094 seconds.