-
Notifications
You must be signed in to change notification settings - Fork 13
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
shared_ptr use_count corruption / no downcasts with shared_ptr #4
Comments
This tests the issue reported in #4 (and seems to invalidate the issue by succeeding).
It works if you don't include shared_ptr_converter.hpp, please try it again using shared_ptr_converter.hpp. |
I have added additional checks to test_automatic_smart_pointer in f9499ec now. I think this should quite exactly mirror what you reported as causing an error. However, I could not reproduce the problem at least with MSVC 11 (both x32 and x64), Lua 5.2 and Boost 1.53. I've also tried Your new comment came just in: I think I will just remove this header to save others from running into this trap. Thanks for reporting. |
If you don't include shared_ptr_converter luabind should not be able to downcast smart pointers (static_pointer_cast) as far as I tested, that was a few months ago though and with the original luabind branch. Did that change? Edit: I just tried it without shared_ptr_converter, it does exactly what I suspected: It isn't able to downcast the smart_pointer. lua> runtime error: No matching overload found. The function expects a shared_ptr<base and I'm passing a shared_ptr<derived to it. |
If by original branch, you mean the last official release, then I don't think so. If you mean the luabind/luabind master branch, then I don't know. |
Regarding your question: Yes it does work with plain pointers. shared_ptr_converter basically extend that support for smart pointers. It tells luabind to treat the holder type as pointer type so it can apply static_pointer_cast. Btw: Deutsch? :P |
Thank you. I will investigate this. |
I just found a post regarding this bug from Daniel Wallin: http://lua.2524044.n2.nabble.com/double-deletion-problem-with-shared-pointers-td7582150.html After looking at it I saw that shared_ptr_converter adds a custom deleter which does some unref thing in the lua registry once your pointer runs out of scope, you must not call lua_close before any such objects are gone :( Here is my modified shared_ptr_converter which enables downcasting for std::shared_ptr types. You might want to add that functionality to yours.
|
From what I read, what this
For Lua -> C++, they only have access to the raw pointer and create a new The custom deleter contains a strong Lua reference to luabind's internal representation of the object, thus preventing it's collection. Upon deletion it just releases this reference. This means that when there exist no other references to the object (from other I do not know how I could possibly fix this. Sorry. Maybe there will be more insights at luabind#18 or rpavlik#9. Workarounds
EDIT: If you know any other Lua/C++ binding library that is able to cast smart pointers, please let me know: it could be a great help in fixing this. EDIT2: The LuaBridge documentation also regards this as undoable, a pull request that adds support for |
Wouldn't this result in a bad_weak_ptr exception? I really hate intrusive_ptr because you cannot hold weak references / weak references don't know if the object is destroyed. I guess I will just prevent the lua_State from being closed while any references to lua objects remain in my code (shared_ptr deleters). I shouldn't run into problems then. The only real problem is lua_close... EDIT: Wouldn't it be possible to fix the shared_ptr ref count if luabind constructs the shared_ptr from lua->c++ with enable_shared_from_raw? |
If you pass the object by
I hear from |
I have now implemented a fix/workaround (needs more testing and possibly refinement before pushing -- here's a gist: https://gist.github.com/Oberon00/6151412) which is based on
For caveat (2) of 2.: Avoiding this issue by checking if the type has |
I added a workaround. I'm simply not destroying the lua state until every object which has a back reference to lua is destroyed. Thanks for looking into it. Regarding 2.2: I guess that way it wont work if you got 1 base class which inherits enable_shared_from_this<BaseClass and this base class is inherited by the class hierarchy and upcast with dynamic_pointer_cast<T ? If not you could eventually force the user to inherit a base class which inherits enable_shared_from_this<BaseClass and check if the type is derived from that base class. This behaviour could be added to wrap_base. |
This tests the issue reported in #4 (and seems to invalidate the issue by succeeding).
So the only real problem at the moment is raw equality right? |
This raw equality problem (which occurs when passing a pointer of any kind(1) from Lua and then back again or (2) to Lua multiple times) is not specific to smart pointers: To the contrary, a shared_ptr was (or is in case 3 of the fix) the only way to preserve raw equality but even then only for one that originally came from Lua via shared_ptr_converter. Even with raw pointers, raw equality is lost. To fix it, luabind would have to maintain a state-global table with an address->object mapping to always use the same object for the same pointer. However, the only case where this really matters is when using the objects as table indices and when you want to use The problem still left with But I really reopened this issue because I think that I should provide upcasting capabilities for more smart pointers, namely |
Thank you very much! I'm so glad this is resolved now. I believe shared_ptr support can be considered complete now. |
Yes, it more or less has to, as I said above
|
The test attemts to index Lua tables with Luabind objects and tests if logically equal objects are treated as denoting the same table element when used as key. But that is not and *cannot* be the case, as the Lua Reference Manual points out (http://www.lua.org/manual/5.2/manual.html#2.1): > The indexing of tables follows the definition of raw equality in the > language. The expressions a[i] and a[j] denote the same table element if and > only if i and j are raw equal (that is, equal without metamethods). Note especially the last, parenthesized statement. It follows that the test does not show a bug in Luabind but rather the "limitations" of the Lua language.
Hoping to get this in my repo if it's reasonably separable, though it might be as a more full merge, instead. |
This tests the issue reported here: Oberon00#4 Credits to @Oberon00
This tests the issue reported here: Oberon00#4 Credits to @Oberon00
Luabind causes a shared_ptr corruption when you do this in lua:
where the C++ export looks like that:
Now when you do the following you will get a use_count == 1 where it should actually be 2 because lua should hold a shared_ptr and your code should:
This is a huge problem when your GC runs because it always thinks the shared_ptr is the only one in use and it will always release objects created like that, not matter if a ptr is used by the c++ code atm.
Example:
The problem exists in lua 5.1 and 5.2, everywhere I checked
The text was updated successfully, but these errors were encountered: