Rapptz / sol

A C++11 Lua wrapper
MIT License
209 stars 32 forks source link

sol::table:size() #63

Open iganinja opened 9 years ago

iganinja commented 9 years ago

Hi

I am very new to github so please forgive my noobness: I started using Sol and managed to integrate it (it's very easy, no problem here) in my test program. I tried the following: load a lua file which has a generateDungeon function which returns a 4096 elements table. Then in C++ I do the following:

sol::function dungeonFunc = luaVM.get<sol::function>("generateDungeon");
sol::table dungeon = dungeonFunc.call<sol::table>();

Everything works flawlessly but when I want to read all the values from table:

for(std::size_t i = 1; i <= dungeon.size(); ++ i)
{
    const auto value = dungeon.get<int>(i);

    // etc...
}

loop finishes but I have seg fault errors in random places. I tested commenting here and there and my conclusion points to sol::table::size(). I took dungeon.size() call out from for loop:

auto dungeonSize = dungeon.size();
for(std::size_t i = 1; i <= dungeonSize; ++ i)

With this change everything works. I checked sol::table:size() and we have the following:

size_t size() const {
    push();
    return lua_rawlen(state(), -1);
}

With my total lack of knowledge of how sol and lua work, I would say that push() makes some stack get bigger in each call to size() and finally makes my app crash. Is it possible this to be a bug?

Thanks for your library by the way ;)

Regards

ThePhD commented 9 years ago

It's a bug that's been fixed here: https://github.com/Rapptz/sol/pull/61#discussion_r30457613 . If you want the fix, pull from the develop branch of sol.

Note that in the develop branch, specifically to get around this problem, we created table.for_each function for your use. Please note that the iteration of lua is not guaranteed to get in numeric order, however.

Also, be careful: the raw length is the number of consecutive integer/number keys. If a table happens to have string keys, that size will only count up to that first string key, and then you'll stop before hitting the rest of the table's keys and values. Finally, if you know for CERTAIN that you'll only have integers for keys, then your table should be just fine; this is just a heads up! Happy coding.

ThePhD commented 9 years ago

One final note: the develop branch deprecates userdata as a name (and a few of its poorly made functions) and has usertype instead, so if you're using userdata<T>, you may have to go through and change them to usertype<T>.

iganinja commented 9 years ago

Thanks for this quick and extensive response ;) My fault not looking at develop branch, only in the master one.