mirror of
https://github.com/ThePhD/sol2.git
synced 2024-03-22 13:10:44 +08:00
Fix leak issues and some ordering in state(view) move operations. Closes #336.
This commit is contained in:
parent
fe8b1c1c10
commit
85194e0135
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -71,3 +71,4 @@ LuaJIT-2.1.0/
|
||||||
lua-5.3.3-cxx/
|
lua-5.3.3-cxx/
|
||||||
lua-5.3.3.vcxproj-cxx.filters
|
lua-5.3.3.vcxproj-cxx.filters
|
||||||
sol.pyproj
|
sol.pyproj
|
||||||
|
lua-5.3.3.dll
|
||||||
|
|
|
@ -20,8 +20,8 @@
|
||||||
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
// This file was generated with a script.
|
// This file was generated with a script.
|
||||||
// Generated 2017-02-01 11:49:07.483904 UTC
|
// Generated 2017-02-15 10:41:27.152230 UTC
|
||||||
// This header was generated with sol v2.15.7 (revision 8d6f304)
|
// This header was generated with sol v2.15.7 (revision fe8b1c1)
|
||||||
// https://github.com/ThePhD/sol2
|
// https://github.com/ThePhD/sol2
|
||||||
|
|
||||||
#ifndef SOL_SINGLE_INCLUDE_HPP
|
#ifndef SOL_SINGLE_INCLUDE_HPP
|
||||||
|
@ -3953,6 +3953,9 @@ namespace sol {
|
||||||
}
|
}
|
||||||
|
|
||||||
reference& operator=(reference&& o) noexcept {
|
reference& operator=(reference&& o) noexcept {
|
||||||
|
if (valid()) {
|
||||||
|
deref();
|
||||||
|
}
|
||||||
luastate = o.luastate;
|
luastate = o.luastate;
|
||||||
ref = o.ref;
|
ref = o.ref;
|
||||||
|
|
||||||
|
@ -4610,7 +4613,39 @@ namespace sol {
|
||||||
|
|
||||||
namespace sol {
|
namespace sol {
|
||||||
namespace detail {
|
namespace detail {
|
||||||
#ifdef _MSC_VER
|
#if defined(__GNUC__) || defined(__clang__)
|
||||||
|
template <typename T, class seperator_mark = int>
|
||||||
|
inline std::string ctti_get_type_name() {
|
||||||
|
const static std::array<std::string, 2> removals = { { "{anonymous}", "(anonymous namespace)" } };
|
||||||
|
std::string name = __PRETTY_FUNCTION__;
|
||||||
|
std::size_t start = name.find_first_of('[');
|
||||||
|
start = name.find_first_of('=', start);
|
||||||
|
std::size_t end = name.find_last_of(']');
|
||||||
|
if (end == std::string::npos)
|
||||||
|
end = name.size();
|
||||||
|
if (start == std::string::npos)
|
||||||
|
start = 0;
|
||||||
|
if (start < name.size() - 1)
|
||||||
|
start += 1;
|
||||||
|
name = name.substr(start, end - start);
|
||||||
|
start = name.rfind("seperator_mark");
|
||||||
|
if (start != std::string::npos) {
|
||||||
|
name.erase(start - 2, name.length());
|
||||||
|
}
|
||||||
|
while (!name.empty() && std::isblank(name.front())) name.erase(name.begin());
|
||||||
|
while (!name.empty() && std::isblank(name.back())) name.pop_back();
|
||||||
|
|
||||||
|
for (std::size_t r = 0; r < removals.size(); ++r) {
|
||||||
|
auto found = name.find(removals[r]);
|
||||||
|
while (found != std::string::npos) {
|
||||||
|
name.erase(found, removals[r].size());
|
||||||
|
found = name.find(removals[r]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
#elif defined(_MSC_VER)
|
||||||
template <typename T>
|
template <typename T>
|
||||||
inline std::string ctti_get_type_name() {
|
inline std::string ctti_get_type_name() {
|
||||||
const static std::array<std::string, 7> removals = { { "public:", "private:", "protected:", "struct ", "class ", "`anonymous-namespace'", "`anonymous namespace'" } };
|
const static std::array<std::string, 7> removals = { { "public:", "private:", "protected:", "struct ", "class ", "`anonymous-namespace'", "`anonymous namespace'" } };
|
||||||
|
@ -4641,38 +4676,6 @@ namespace sol {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
#elif defined(__GNUC__) || defined(__clang__)
|
|
||||||
template <typename T, class seperator_mark = int>
|
|
||||||
inline std::string ctti_get_type_name() {
|
|
||||||
const static std::array<std::string, 2> removals = { { "{anonymous}", "(anonymous namespace)" } };
|
|
||||||
std::string name = __PRETTY_FUNCTION__;
|
|
||||||
std::size_t start = name.find_first_of('[');
|
|
||||||
start = name.find_first_of('=', start);
|
|
||||||
std::size_t end = name.find_last_of(']');
|
|
||||||
if (end == std::string::npos)
|
|
||||||
end = name.size();
|
|
||||||
if (start == std::string::npos)
|
|
||||||
start = 0;
|
|
||||||
if (start < name.size() - 1)
|
|
||||||
start += 1;
|
|
||||||
name = name.substr(start, end - start);
|
|
||||||
start = name.rfind("seperator_mark");
|
|
||||||
if (start != std::string::npos) {
|
|
||||||
name.erase(start - 2, name.length());
|
|
||||||
}
|
|
||||||
while (!name.empty() && std::isblank(name.front())) name.erase(name.begin());
|
|
||||||
while (!name.empty() && std::isblank(name.back())) name.pop_back();
|
|
||||||
|
|
||||||
for (std::size_t r = 0; r < removals.size(); ++r) {
|
|
||||||
auto found = name.find(removals[r]);
|
|
||||||
while (found != std::string::npos) {
|
|
||||||
name.erase(found, removals[r].size());
|
|
||||||
found = name.find(removals[r]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
|
@ -12885,7 +12888,11 @@ namespace sol {
|
||||||
state(const state&) = delete;
|
state(const state&) = delete;
|
||||||
state(state&&) = default;
|
state(state&&) = default;
|
||||||
state& operator=(const state&) = delete;
|
state& operator=(const state&) = delete;
|
||||||
state& operator=(state&&) = default;
|
state& operator=(state&& that) {
|
||||||
|
state_view::operator=(std::move(that));
|
||||||
|
unique_base::operator=(std::move(that));
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
using state_view::get;
|
using state_view::get;
|
||||||
|
|
||||||
|
|
|
@ -28,7 +28,39 @@
|
||||||
|
|
||||||
namespace sol {
|
namespace sol {
|
||||||
namespace detail {
|
namespace detail {
|
||||||
#ifdef _MSC_VER
|
#if defined(__GNUC__) || defined(__clang__)
|
||||||
|
template <typename T, class seperator_mark = int>
|
||||||
|
inline std::string ctti_get_type_name() {
|
||||||
|
const static std::array<std::string, 2> removals = { { "{anonymous}", "(anonymous namespace)" } };
|
||||||
|
std::string name = __PRETTY_FUNCTION__;
|
||||||
|
std::size_t start = name.find_first_of('[');
|
||||||
|
start = name.find_first_of('=', start);
|
||||||
|
std::size_t end = name.find_last_of(']');
|
||||||
|
if (end == std::string::npos)
|
||||||
|
end = name.size();
|
||||||
|
if (start == std::string::npos)
|
||||||
|
start = 0;
|
||||||
|
if (start < name.size() - 1)
|
||||||
|
start += 1;
|
||||||
|
name = name.substr(start, end - start);
|
||||||
|
start = name.rfind("seperator_mark");
|
||||||
|
if (start != std::string::npos) {
|
||||||
|
name.erase(start - 2, name.length());
|
||||||
|
}
|
||||||
|
while (!name.empty() && std::isblank(name.front())) name.erase(name.begin());
|
||||||
|
while (!name.empty() && std::isblank(name.back())) name.pop_back();
|
||||||
|
|
||||||
|
for (std::size_t r = 0; r < removals.size(); ++r) {
|
||||||
|
auto found = name.find(removals[r]);
|
||||||
|
while (found != std::string::npos) {
|
||||||
|
name.erase(found, removals[r].size());
|
||||||
|
found = name.find(removals[r]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
#elif defined(_MSC_VER)
|
||||||
template <typename T>
|
template <typename T>
|
||||||
inline std::string ctti_get_type_name() {
|
inline std::string ctti_get_type_name() {
|
||||||
const static std::array<std::string, 7> removals = { { "public:", "private:", "protected:", "struct ", "class ", "`anonymous-namespace'", "`anonymous namespace'" } };
|
const static std::array<std::string, 7> removals = { { "public:", "private:", "protected:", "struct ", "class ", "`anonymous-namespace'", "`anonymous namespace'" } };
|
||||||
|
@ -59,38 +91,6 @@ namespace sol {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
#elif defined(__GNUC__) || defined(__clang__)
|
|
||||||
template <typename T, class seperator_mark = int>
|
|
||||||
inline std::string ctti_get_type_name() {
|
|
||||||
const static std::array<std::string, 2> removals = { { "{anonymous}", "(anonymous namespace)" } };
|
|
||||||
std::string name = __PRETTY_FUNCTION__;
|
|
||||||
std::size_t start = name.find_first_of('[');
|
|
||||||
start = name.find_first_of('=', start);
|
|
||||||
std::size_t end = name.find_last_of(']');
|
|
||||||
if (end == std::string::npos)
|
|
||||||
end = name.size();
|
|
||||||
if (start == std::string::npos)
|
|
||||||
start = 0;
|
|
||||||
if (start < name.size() - 1)
|
|
||||||
start += 1;
|
|
||||||
name = name.substr(start, end - start);
|
|
||||||
start = name.rfind("seperator_mark");
|
|
||||||
if (start != std::string::npos) {
|
|
||||||
name.erase(start - 2, name.length());
|
|
||||||
}
|
|
||||||
while (!name.empty() && std::isblank(name.front())) name.erase(name.begin());
|
|
||||||
while (!name.empty() && std::isblank(name.back())) name.pop_back();
|
|
||||||
|
|
||||||
for (std::size_t r = 0; r < removals.size(); ++r) {
|
|
||||||
auto found = name.find(removals[r]);
|
|
||||||
while (found != std::string::npos) {
|
|
||||||
name.erase(found, removals[r].size());
|
|
||||||
found = name.find(removals[r]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
|
|
|
@ -116,6 +116,9 @@ namespace sol {
|
||||||
}
|
}
|
||||||
|
|
||||||
reference& operator=(reference&& o) noexcept {
|
reference& operator=(reference&& o) noexcept {
|
||||||
|
if (valid()) {
|
||||||
|
deref();
|
||||||
|
}
|
||||||
luastate = o.luastate;
|
luastate = o.luastate;
|
||||||
ref = o.ref;
|
ref = o.ref;
|
||||||
|
|
||||||
|
|
|
@ -78,7 +78,11 @@ namespace sol {
|
||||||
state(const state&) = delete;
|
state(const state&) = delete;
|
||||||
state(state&&) = default;
|
state(state&&) = default;
|
||||||
state& operator=(const state&) = delete;
|
state& operator=(const state&) = delete;
|
||||||
state& operator=(state&&) = default;
|
state& operator=(state&& that) {
|
||||||
|
state_view::operator=(std::move(that));
|
||||||
|
unique_base::operator=(std::move(that));
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
using state_view::get;
|
using state_view::get;
|
||||||
|
|
||||||
|
|
|
@ -1246,10 +1246,10 @@ TEST_CASE("usertype/shared-ptr-regression", "usertype metatables should not scre
|
||||||
REQUIRE(destroyed == 1);
|
REQUIRE(destroyed == 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("usertype/double-deleter-guards", "usertype metatables internally must not rely on internal ") {
|
TEST_CASE("usertype/double-deleter-guards", "usertype metatables internally must not rely on C++ state") {
|
||||||
struct c_a { int x; };
|
struct c_a { int x; };
|
||||||
struct c_b { int y; };
|
struct c_b { int y; };
|
||||||
REQUIRE_NOTHROW( {
|
auto routine = []() {
|
||||||
sol::state lua;
|
sol::state lua;
|
||||||
lua.new_usertype<c_a>("c_a", "x", &c_a::x);
|
lua.new_usertype<c_a>("c_a", "x", &c_a::x);
|
||||||
lua.new_usertype<c_b>("c_b", "y", &c_b::y);
|
lua.new_usertype<c_b>("c_b", "y", &c_b::y);
|
||||||
|
@ -1257,7 +1257,8 @@ TEST_CASE("usertype/double-deleter-guards", "usertype metatables internally must
|
||||||
lua.new_usertype<c_a>("c_a", "x", &c_a::x);
|
lua.new_usertype<c_a>("c_a", "x", &c_a::x);
|
||||||
lua.new_usertype<c_b>("c_b", "y", &c_b::y);
|
lua.new_usertype<c_b>("c_b", "y", &c_b::y);
|
||||||
lua = sol::state();
|
lua = sol::state();
|
||||||
});
|
};
|
||||||
|
REQUIRE_NOTHROW(routine());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("usertype/vars", "usertype vars can bind various class items") {
|
TEST_CASE("usertype/vars", "usertype vars can bind various class items") {
|
||||||
|
|
80
tests.cpp
80
tests.cpp
|
@ -445,6 +445,21 @@ TEST_CASE("state/multi-require", "make sure that requires transfers across hand-
|
||||||
REQUIRE(thingy2 == thingy3);
|
REQUIRE(thingy2 == thingy3);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_CASE("state/require-safety", "make sure unrelated modules aren't harmed in using requires") {
|
||||||
|
sol::state lua;
|
||||||
|
lua.open_libraries();
|
||||||
|
std::string t1 = lua.script(R"(require 'io'
|
||||||
|
return 'test1')");
|
||||||
|
sol::object ot2 = lua.require_script("test2", R"(require 'io'
|
||||||
|
return 'test2')");
|
||||||
|
std::string t2 = ot2.as<std::string>();
|
||||||
|
std::string t3 = lua.script(R"(require 'io'
|
||||||
|
return 'test3')");
|
||||||
|
REQUIRE(t1 == "test1");
|
||||||
|
REQUIRE(t2 == "test2");
|
||||||
|
REQUIRE(t3 == "test3");
|
||||||
|
}
|
||||||
|
|
||||||
TEST_CASE("feature/indexing-overrides", "make sure index functions can be overridden on types") {
|
TEST_CASE("feature/indexing-overrides", "make sure index functions can be overridden on types") {
|
||||||
struct PropertySet {
|
struct PropertySet {
|
||||||
sol::object get_property_lua(const char* name, sol::this_state s)
|
sol::object get_property_lua(const char* name, sol::this_state s)
|
||||||
|
@ -717,6 +732,51 @@ TEST_CASE("numbers/integers", "make sure integers are detectable on most platfor
|
||||||
REQUIRE(b_is_double);
|
REQUIRE(b_is_double);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_CASE("state/leak-check", "make sure there are no humongous memory leaks in iteration") {
|
||||||
|
sol::state lua;
|
||||||
|
lua.script(R"(
|
||||||
|
record = {}
|
||||||
|
for i=1,256 do
|
||||||
|
record[i] = i
|
||||||
|
end
|
||||||
|
function run()
|
||||||
|
for i=1,25000 do
|
||||||
|
fun(record)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
function run2()
|
||||||
|
for i=1,50000 do
|
||||||
|
fun(record)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
)");
|
||||||
|
|
||||||
|
lua["fun"] = [](const sol::table &t) {
|
||||||
|
//removing the for loop fixes the memory leak
|
||||||
|
auto b = t.begin();
|
||||||
|
auto e = t.end();
|
||||||
|
for (; b != e; ++b) {
|
||||||
|
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
size_t beforewarmup = lua.memory_used();
|
||||||
|
lua["run"]();
|
||||||
|
|
||||||
|
size_t beforerun = lua.memory_used();
|
||||||
|
lua["run"]();
|
||||||
|
size_t afterrun = lua.memory_used();
|
||||||
|
lua["run2"]();
|
||||||
|
size_t afterrun2 = lua.memory_used();
|
||||||
|
|
||||||
|
// Less memory used before the warmup
|
||||||
|
REQUIRE(beforewarmup <= beforerun);
|
||||||
|
// Iteration size and such does not bloat or affect memory
|
||||||
|
// (these are weak checks but they'll warn us nonetheless if something goes wrong)
|
||||||
|
REQUIRE(beforerun == afterrun);
|
||||||
|
REQUIRE(afterrun == afterrun2);
|
||||||
|
}
|
||||||
|
|
||||||
TEST_CASE("state/script-returns", "make sure script returns are done properly") {
|
TEST_CASE("state/script-returns", "make sure script returns are done properly") {
|
||||||
std::string script =
|
std::string script =
|
||||||
R"(
|
R"(
|
||||||
|
@ -792,3 +852,23 @@ return example;
|
||||||
|
|
||||||
lua.script("bar() bar2() foo(1) foo2(1)");
|
lua.script("bar() bar2() foo(1) foo2(1)");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_CASE("state/copy-move", "ensure state can be properly copied and moved") {
|
||||||
|
sol::state lua;
|
||||||
|
lua["a"] = 1;
|
||||||
|
|
||||||
|
sol::state lua2(std::move(lua));
|
||||||
|
int a2 = lua2["a"];
|
||||||
|
REQUIRE(a2 == 1);
|
||||||
|
lua = std::move(lua2);
|
||||||
|
int a = lua["a"];
|
||||||
|
REQUIRE(a == 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("requires/reload", "ensure that reloading semantics do not cause a crash") {
|
||||||
|
sol::state lua;
|
||||||
|
lua.open_libraries();
|
||||||
|
lua.script("require 'io'\nreturn 'test1'");
|
||||||
|
lua.require_script("test2", "require 'io'\nreturn 'test2'");
|
||||||
|
lua.script("require 'io'\nreturn 'test3'");
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user