segfault when get_pointer returns null
Andreas Grob <[email protected]>
| Newsgroups | gmane.comp.lang.lua.bind.user |
|---|---|
| Message-ID | <1298761033.6662.42.camel@debian> |
Hello all,
right now I am trying to write a wrapping pointer to hold objects passed
to luabind. The idea is to change the behaviour of get_pointer at
runtime to invalidate objects.
While I can wrap null pointers and receive luabind::error upon trying to
call a member, the program segfaults in luabind when I change the result
of get_pointer from a normal pointer to null at a later time, i.e. after
passing the wrapped object to luabind.
Here is the stacktrace when get_pointer just returned null before the
segfault:
#0 luabind::detail::pointer_holder<fuse_ptr<myclass>, void const>::get
(this=0x805b630, target=3)
at /usr/include/luabind/detail/instance_holder.hpp:100
#1 0x0804bd60 in luabind::detail::object_rep::get_instance
(this=0x805b62c, target=3)
at /usr/include/luabind/detail/object_rep.hpp:59
#2 0x0804f99a in luabind::detail::ref_converter::match<myclass>
(this=0xbfffee94, L=0x80550a8, index=1)
at /usr/include/luabind/detail/policy.hpp:402
#3 0x0804f776 in luabind::detail::invoke_member<void (myclass::*)(),
boost::mpl::vector2<void, myclass&>, luabind::detail::null_type>
(L=0x80550a8, self=..., ctx=..., f=@0x805a5b8)
at /usr/include/luabind/detail/call.hpp:257
#4 0x0804f6d3 in luabind::detail::invoke0<void (myclass::*)(),
boost::mpl::vector2<void, myclass&>, luabind::detail::null_type,
boost::is_void<void> > (L=0x80550a8, self=..., ctx=..., f=@0x805a5b8,
policies=...) at /usr/include/luabind/detail/call.hpp:78
#5 0x0804f698 in luabind::detail::invoke<void (myclass::*)(),
boost::mpl::vector2<void, myclass&>, luabind::detail::null_type> (
L=0x80550a8, self=..., ctx=..., f=@0x805a5b8, policies=...)
at /usr/include/luabind/detail/call.hpp:101
#6 0x0804f5d6 in luabind::detail::function_object_impl<void
(myclass::*)(), boost::mpl::vector2<void, myclass&>,
luabind::detail::null_type>::entry_point (L=0x80550a8)
at /usr/include/luabind/make_function.hpp:62
[...calls from lua...]
If continued it segfaults in frame 3, line 287:
(c0.apply(L, LUABIND_DECORATE_TYPE(a0), index0).*f)(
My question is: Why is the call to a member of null not detected and an
exception thrown?
The code is attached (using lua 5.1.4 and luabind 0.9.1).
Thank you very much.
Best regards,
Andreas
------------------------------------------------------------------------------
Free Software Download: Index, Search & Analyze Logs and other IT data in
Real-Time with Splunk. Collect, index and harness all the fast moving IT data
generated by your applications, servers and devices whether physical, virtual
or in the cloud. Deliver compliance at lower cost and gain new business
insights. http://p.sf.net/sfu/splunk-dev2dev
_______________________________________________
luabind-user mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/luabind-user
fuse_ptr.hpp
(text/x-c++hdr, 3 KB)
#ifndef __FUSE_PTR_HPP__
#define __FUSE_PTR_HPP__
#include <map>
#include <iostream>
template<class T>
class fuse_ptr
{
private:
// pointer to the object
T** ptr;
// container for all references from pointers to associated fuse_ptrs
static std::multimap<T*,fuse_ptr<T> * > fusebox;
public:
// contructor for null pointer
fuse_ptr()
{
ptr = new T*;
*ptr = 0;
}
// constructor for objects
fuse_ptr( T* p )
{
ptr = new T*;
*ptr = p;
std::cout << this << " is now fuse for " << *ptr << std::endl;
fusebox.insert( std::pair<T*,fuse_ptr<T> * >(p,this) );
}
// copy constructor
fuse_ptr( fuse_ptr const & p )
{
ptr = new T*;
*ptr = *(p.ptr);
std::cout << this << " is now fuse for " << *ptr << std::endl;
fusebox.insert( std::pair<T*,fuse_ptr<T> * >(*ptr,this) );
}
// pointer access
T* get() const
{
std::cout << "Getting ptr of " << this << ": " << *ptr << std::endl;
return *ptr;
}
operator T*() const
{
return get();
}
T* operator->() const
{
return get();
}
operator bool() const
{
return get() != 0;
}
// virtual destructor
virtual ~fuse_ptr()
{
if( *ptr != 0 )
{
std::pair< typename std::multimap<T*,fuse_ptr<T> * >::iterator, typename std::multimap<T*,fuse_ptr<T> * >::iterator > range = fusebox.equal_range( *ptr );
typename std::multimap<T*,fuse_ptr<T> * >::iterator it;
for( it = range.first; it != range.second && it->second != this; ++it );
if( it != range.second )
{
std::cout << this << " is not any longer fuse for " << it->first << std::endl;
fusebox.erase( it );
}
}
delete ptr;
ptr = 0;
}
// sets all associated fuse_ptrs' contents to null and removes them from fusebox
static void blow_fuse( T* p )
{
std::pair< typename std::multimap<T*,fuse_ptr<T> * >::iterator, typename std::multimap<T*,fuse_ptr<T> * >::iterator > range = fusebox.equal_range( p );
typename std::multimap<T*,fuse_ptr<T> * >::iterator it;
for( it = range.first; it != range.second; ++it )
{
std::cout << "Setting *ptr of " << it->second << " = 0" << std::endl;
*(it->second->ptr) = 0;
}
fusebox.erase( p );
}
};
template<class T>
std::multimap<T*,fuse_ptr<T> * > fuse_ptr<T>::fusebox;
// returns p.get()
template<class T>
T* get_pointer( fuse_ptr<T> const & p )
{
return p.get();
}
#endif
main.cpp
(text/x-c++src, 1.9 KB)
#include <iostream>
#include <sstream>
#include "fuse_ptr.hpp"
#include <lua5.1/lua.hpp>
#include <luabind/luabind.hpp>
using namespace std;
using namespace luabind;
class myclass
{
public:
myclass()
{
cout << "myclass created: " << this << endl;
someint = 42;
}
myclass(int dummy)
{
cout << "myclass created: " << this << endl;
someint = dummy;
}
~myclass()
{
fuse_ptr<myclass>::blow_fuse( this );
cout << "myclass destructed: " << this << endl;
}
virtual void dosomething()
{
cout << "someint == " << someint << endl;
}
protected:
int someint;
};
int main(void)
{
lua_State* L = lua_open();
luaL_openlibs( L );
open( L );
module(L)
[
class_<myclass, fuse_ptr<myclass> >("myclass")
.def( "dosomething", &myclass::dosomething )
];
const char* src = "function doStuff()"
" stored_myc:dosomething();"
"end;"
"function storeMyc( myc )"
" stored_myc = myc;"
"end;";
if( luaL_dostring( L, src ) )
{
cout << "Error:" << lua_tostring( L, -1 ) << endl;
}
try
{
myclass* p = new myclass(100);
myclass* q = 0;
// using q here instead of p works
fuse_ptr<myclass> f(p);
globals( L )["storeMyc"](f);
globals( L )["doStuff"]();
delete p;
p=0;
globals( L )["doStuff"]();
delete q;
q=0;
}
catch(luabind::error e)
{
cout<<"caught exception..."<<endl;
cout<<e.what()<<endl;
std::string err = lua_tostring(L, -1);
lua_pop(L, 1);
cout<<err<<endl;
}
cout << "closing luaState..." << endl;
lua_close( L );
cout << "return 0" << endl;
return 0;
}