ThePhD / sol2

Sol3 (sol2 v3.0) - a C++ <-> Lua API wrapper with advanced features and top notch performance - is here, and it's great! Documentation:
http://sol2.rtfd.io/
MIT License
4.23k stars 518 forks source link

Multiple registrations of the same type (even at different names) behave weirdly #1492

Open devgs opened 1 year ago

devgs commented 1 year ago

I've simplified one of the examples and added a repeated registration of the same type. Depending on the number of registrations (cycles) script will either work as expected or throw an error attempt to index a sol.foo value (global 'x').

For me it breaks at 2, works at 3, 4, then breaks again at 5, works at 6, 7, breaks again at 8, ...

I've tried multiple things: using different names, manual unregistering with no avail. Decided not to complicate the example.

Looking at the source code and tests it seems that this should work as each new registration shall replace the previous one, if any. It seems that somehow the metatable gets broken, but I'm unable to track down the specific place.

#define SOL_ALL_SAFETIES_ON 1
#include <sol/sol.hpp>

#include <iostream>

struct foo {
private:
    std::string name;

public:
    foo(std::string name) : name(std::string(name)) {
    }

    void print() {
        std::cout << name << '\n';
    }

    int test(int x) {
        return static_cast<int>(name.length()) + x;
    }
};

int main() {
    const std::size_t CYCLE_NUMBER = 2;
    sol::state lua;
    lua.open_libraries(sol::lib::base, sol::lib::math);

    for (std::size_t i = 0; i < CYCLE_NUMBER; ++i) {
        lua.new_usertype<foo>("foo",
             sol::constructors<foo(std::string)>(),
             "print",
             &foo::print,
             "test",
             &foo::test);
    }

    lua.script(
         "x = foo.new('test')\n"
         "x:print()\n"
         "y = x:test(10)");

    auto y = lua.get<int>("y");
    std::cout << y << std::endl; // show 14
    return 0;
}
Rochet2 commented 1 year ago

Looks like on godbolt it works with:

Lua 5.3.5
sol2 3.2.1
-std=c++17
x86-64 gcc 10.1

It could be a compiler specific issue. A git bisect or similar could be done to find which commit breaks it. Maybe you could post your compiler platform+version and try the working versions above if you can reproduce with them.

devgs commented 1 year ago

Huh!

Actually I was using a develop branch. Then I've bisected tags down to v3.3.0. It seems to be the version where the bug was introduced. Indeed, on v3.2.1 everything is fine. How unfortunate.