# sol2 3.5.0 documentation

## ownership

### Search the Documentation

# ownership

Ownership is important when managing resources in C++. sol has many ownership semantics which are generally safe by default. Below are the rules.

## object ownership

You can take a reference to something that exists in Lua by pulling out a sol::reference or a sol::object:

object_lifetime.cpp

     1#define SOL_ALL_SAFETIES_ON 1
     2#include <sol/sol.hpp>
     3
     4#include <string>
     5#include <iostream>
     6
     7int main() {
     8	sol::state lua;
     9	lua.open_libraries(sol::lib::base);
    10
    11	lua.script(R"(
    12	obj = "please don't let me die";
    13	)");
    14
    15	sol::object keep_alive = lua["obj"];
    16	lua.script(R"(
    17	obj = nil;
    18	function say(msg)
    19		print(msg)
    20	end
    21	)");
    22
    23	lua.collect_garbage();
    24
    25	lua["say"](lua["obj"]);
    26	// still accessible here and still alive in Lua
    27	// even though the name was cleared
    28	std::string message = keep_alive.as<std::string>();
    29	std::cout << message << std::endl;
    30
    31	// Can be pushed back into Lua as an argument
    32	// or set to a new name,
    33	// whatever you like!
    34	lua["say"](keep_alive);
    35
    36	return 0;
    37}

All objects must be destroyed before the sol::state is destroyed, otherwise you will end up with dangling references to the Lua State and things will explode in horrible, terrible fashion.

This applies to more than just sol::object: all types derived from sol::reference and sol::object (sol::table sol::userdata, etc.) must be cleaned up before the state goes out of scope.

## pointer ownership

sol will not take ownership of raw pointers: raw pointers do not own anything. sol will not delete raw pointers, because they do not (and are not supposed to) own anything:

pointer_lifetime.cpp

     1#define SOL_ALL_SAFETIES_ON 1
     2#include <sol/sol.hpp>
     3
     4struct my_type {
     5	void stuff() {
     6	}
     7};
     8
     9int main() {
    10
    11	sol::state lua;
    12	// AAAHHH BAD
    13	// dangling pointer!
    14	lua["my_func"] = []() -> my_type* { return new my_type(); };
    15
    16	// AAAHHH!
    17	lua.set("something", new my_type());
    18
    19	// AAAAAAHHH!!!
    20	lua["something_else"] = new my_type();
    21	// Acceptable, it will set 'something' to nil
    22	// (and delete it on next GC if there's no more references)
    23	lua.set("something", nullptr);
    24
    25	// Also fine
    26	lua["something_else"] = nullptr;
    27
    28	return 0;
    29}

Use/return a `unique_ptr` or `shared_ptr` instead or just return a value:

(smart pointers) pointer_lifetime.cpp

     1#define SOL_ALL_SAFETIES_ON 1
     2#include <sol/sol.hpp>
     3
     4struct my_type {
     5	void stuff() {
     6	}
     7};
     8
     9int main() {
    10
    11	sol::state lua;
    12	// :ok:
    13	lua["my_func0"] = []() -> std::unique_ptr<my_type> {
    14		return std::make_unique<my_type>();
    15	};
    16
    17	// :ok:
    18	lua["my_func1"] = []() -> std::shared_ptr<my_type> {
    19		return std::make_shared<my_type>();
    20	};
    21
    22	// :ok:
    23	lua["my_func2"] = []() -> my_type { return my_type(); };
    24
    25	// :ok:
    26	lua.set(
    27	     "something", std::unique_ptr<my_type>(new my_type()));
    28
    29	std::shared_ptr<my_type> my_shared
    30	     = std::make_shared<my_type>();
    31	// :ok:
    32	// Acceptable, it will set 'something' to nil
    33	// (and delete it on next GC if there's no more references)
    34	lua.set("something", nullptr);
    35
    36	// Also fine
    37	lua["something_else"] = nullptr;
    38
    39	return 0;
    40}

If you have something you know is going to last and you just want to give it to Lua as a reference, then it’s fine too:

(static) pointer_lifetime.cpp

     1#define SOL_ALL_SAFETIES_ON 1
     2#include <sol/sol.hpp>
     3
     4struct my_type {
     5	void stuff() {
     6	}
     7};
     8
     9int main() {
    10
    11	sol::state lua;
    12
    13	// :ok:
    14	auto my_unique = std::make_unique<my_type>();
    15	lua["other_thing"] = std::move(my_unique);
    16	// Acceptable, it will set 'something' to nil
    17	// (and delete it on next GC if there's no more references)
    18	lua.set("something", nullptr);
    19
    20	// Also fine
    21	lua["something_else"] = nullptr;
    22
    23	return 0;
    24}

sol can detect `nullptr`, so if you happen to return it there won’t be any dangling because a `sol::lua_nil` will be pushed. But if you know it’s `nil` beforehand, please return `std::nullptr_t` or `sol::lua_nil`:

(nil/nullptr) pointer_lifetime.cpp

     1#define SOL_ALL_SAFETIES_ON 1
     2#include <sol/sol.hpp>
     3
     4struct my_type {
     5	void stuff() {
     6	}
     7};
     8
     9int main() {
    10
    11	sol::state lua;
    12	// :ok:
    13	lua["my_func5"] = []() -> my_type* {
    14		static my_type mt;
    15		return &mt;
    16	};
    17
    18	// THIS IS STILL BAD DON'T DO IT AAAHHH BAD
    19	// return a unique_ptr that's empty instead
    20	// or be explicit!
    21	lua["my_func6"] = []() -> my_type* { return nullptr; };
    22
    23	// :ok:
    24	lua["my_func7"]
    25	     = []() -> std::nullptr_t { return nullptr; };
    26
    27	// :ok:
    28	lua["my_func8"] = []() -> std::unique_ptr<my_type> {
    29		// default-constructs as a nullptr,
    30		// gets pushed as nil to Lua
    31		return std::unique_ptr<my_type>();
    32		// same happens for std::shared_ptr
    33	};
    34
    35	// Acceptable, it will set 'something' to nil
    36	// (and delete it on next GC if there's no more references)
    37	lua.set("something", nullptr);
    38
    39	// Also fine
    40	lua["something_else"] = nullptr;
    41
    42	return 0;
    43}

## ephermeal (proxy) objects

Proxy and result types are ephermeal. They rely on the Lua stack and their constructors / destructors interact with the Lua stack. This means they are entirely unsafe to return from functions in C++, without very careful attention paid to how they are used that often requires relying on implementation-defined behaviors.

Please be careful when using (protected_)function_result, load_result (especially multiple load/function results in a single C++ function!) stack_reference, and similar stack-based things. If you want to return these things, consider