Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 7 additions & 7 deletions LuaCppInterface/luacppinterface.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,10 @@ class Lua
template<typename SIG>
LuaFunction<SIG> internalCreateFunction( std::shared_ptr< std::function<SIG> > func, lua_CFunction cfunc)
{
LuaFunction<SIG>** ptr = (LuaFunction<SIG>**)lua_newuserdata(state.get(), sizeof(LuaFunction<SIG>**));
auto* ptr = (std::shared_ptr< std::function<SIG> >*)
lua_newuserdata(state.get(), sizeof(std::shared_ptr< std::function<SIG> >*));

ptr = new std::shared_ptr< std::function<SIG> >(func);

lua_newtable(state.get());

Expand All @@ -45,11 +48,8 @@ class Lua

// set the metatable
lua_setmetatable(state.get(), -2);
LuaFunction<SIG> function = LuaFunction<SIG>(state, -1, func);

// instantiate a luafunction that has a weak reference to the state
// that the lua garbage collector will collect.
*ptr = new LuaFunction<SIG>(LuaFunction<SIG>(LuaNoDestructor(state.get()), -1, func));
LuaFunction<SIG> function(LuaNoDestructor(state.get()), -1, func);

lua_pop(state.get(), 1);
return function;
Expand All @@ -58,8 +58,8 @@ class Lua
template<typename SIG>
static int lua_finalizer(lua_State* state)
{
LuaFunction<SIG>** func = (LuaFunction<SIG>**)lua_touserdata(state, lua_upvalueindex(1));
delete *func;
auto* func = (std::shared_ptr< std::function<SIG> >*)lua_touserdata(state, lua_upvalueindex(1));
delete func;
return 0;
};

Expand Down
5 changes: 4 additions & 1 deletion tests/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ if COND_GCOV
MAYBE_COVERAGE=-fprofile-arcs
endif

TESTS = demonstration1 demonstration2 demonstration3 demonstration4 luacpp testcallabletable testchartowideconvert testcoroutineexception testcoroutineexpectedbutnot testcreate testctoluafunction testexceptioninluafunction testextractingasfunctionbutistable testfunction testfunctionerror testfunctionexpectedbutnotcallable testfunctionparams testfunctionparamsreturn testfunctionreturn testgetmetatableonclosedstate testgetsetfunction testgetsetfunction2 testgetsetinsidetable testgetsetinteger testgetsetstring testgetsettable testgetstate testgettypeofvalueat testinvalidscript testpassingfunction testreadinglightuserdatafromuserdata testregistry testresumenoscript testreturnfromnative testreturnfromscript testreturnfromyieldingfunction testreturntablefromlua testreturntablefromnative testscriptexception testsetstring testsetwstring testtable testtableexpectedbutnotable testtableforeachintegerkey testtableforeachstringkey testtypeintstringmorph testtypemorphintwstring testtypestringintmorph testuserdata testuserdataconstructor testuserdatadispose testuserdatamethod testwidetocharconvert
TESTS = demonstration1 demonstration2 demonstration3 demonstration4 luacpp testcallabletable testchartowideconvert testcoroutineexception testcoroutineexpectedbutnot testcreate testctoluafunction testexceptioninluafunction testextractingasfunctionbutistable testfunction testfunctiondoesntleak testfunctionerror testfunctionexpectedbutnotcallable testfunctionparams testfunctionparamsreturn testfunctionreturn testgetmetatableonclosedstate testgetsetfunction testgetsetfunction2 testgetsetinsidetable testgetsetinteger testgetsetstring testgetsettable testgetstate testgettypeofvalueat testinvalidscript testpassingfunction testreadinglightuserdatafromuserdata testregistry testresumenoscript testreturnfromnative testreturnfromscript testreturnfromyieldingfunction testreturntablefromlua testreturntablefromnative testscriptexception testsetstring testsetwstring testtable testtableexpectedbutnotable testtableforeachintegerkey testtableforeachstringkey testtypeintstringmorph testtypemorphintwstring testtypestringintmorph testuserdata testuserdataconstructor testuserdatadispose testuserdatamethod testwidetocharconvert

check_PROGRAMS = $(TESTS)

Expand Down Expand Up @@ -53,6 +53,9 @@ testextractingasfunctionbutistable_LDADD = $(REQUIRED_LIBS)
testfunction_SOURCES = testfunction.cpp lua
testfunction_LDADD = $(REQUIRED_LIBS)

testfunctiondoesntleak_SOURCES = testfunctiondoesntleak.cpp lua
testfunctiondoesntleak_LDADD = $(REQUIRED_LIBS)

testfunctionerror_SOURCES = testfunctionerror.cpp lua
testfunctionerror_LDADD = $(REQUIRED_LIBS)

Expand Down
31 changes: 31 additions & 0 deletions tests/testfunctiondoesntleak.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
// Test for CreateFunction memory leak

#include <memory>
#include <luacppinterface.h>

struct Functor {
std::shared_ptr<int> ptr;

void operator()() const {
// no-op
}
};

int main()
{
Lua lua;

// Create a LuaFunction from a functor that holds a shared_ptr to
// a resource. If the function created via CreateFunction gets
// collected by the GC, the weak pointer will expire after that
std::weak_ptr<int> weak;
{
auto ptr = std::make_shared<int>(0);
weak = ptr;
auto function = lua.CreateFunction<void()>(Functor{ptr});
}

lua.CollectGarbage();

return !weak.expired();
}