using get accessor inside an anonymous method on a wrapped c++ class crashes after 3 times

79 views
Skip to first unread message

nicdex

unread,
Sep 13, 2010, 6:18:32 PM9/13/10
to v8-users
Hi,

I think I've discovered a bug, but before submitting it I wanted to
ask, maybe I'm doing something wrong.

My settings :

v8: trunk (rev #5425)
compiler: mingw32 (gcc 4.4.0)

The problem :

When using a get accessor inside an anonymous function and the
receiver (this) is a C++ wrapped class (internal field pointing to the
c++ object), the AccessorInfo.This() gets corrupted and it crashes
when I try to access the internal field. It always crashes at the
third time.

Here is the gdb callstack :

#0 63E261A2 v8::internal::HeapObject::map_word(this=0xa045f01) (src//
objects-inl.h:1071)
#1 63E2605D v8::internal::HeapObject::map(this=0xa045f01) (src//
objects-inl.h:1061)
#2 63E26081 v8::internal::HeapObject::Size(this=0xa045f01) (src//
objects-inl.h:1094)
#3 63E7AF6E
v8::internal::JSObject::GetInternalFieldCount(this=0xa045f01) (src//
objects-inl.h:1268)
#4 63C51964 v8::Object::CheckedGetInternalField(this=0x31abb4d,
index=0) (src\api.cc:3138)
#5 00420970 v8::Object::GetInternalField(this=0x31abb4d, index=0) (../
include/v8.h:3468)
#6 00425403
Scripting::BitmapGridWrapper::GridXGetter(property={<v8::Handle<v8::String>>
= {val_ = 0x603f814}, <No data fields>}, info=@0x603f82c) (C:\nicdex
\dexdo\DGE\src\scripting\cppbinding.cpp:127)
#7 00000000 0x0d3566bf in ??() (??:??)
#8 00000000 0x0603f814 in ??() (??:??)
#9 00000000 0x0603f82c in ??() (??:??)
#10 00000000 0x0603f83c in ??() (??:??)
#11 00000000 0x00000000 in ??() (??:??)

See attachment for a c++ test file reproducing the bug.

* Note that the callstack is from my original error, not the test, but
it is the same error, only the origin changes.

Thanks for your help.

NicDex

Matthias Ernst

unread,
Sep 14, 2010, 5:25:50 AM9/14/10
to v8-u...@googlegroups.com
There is no attachment. You may want to make it accessible differently.

 
* Note that the callstack is from my original error, not the test, but
it is the same error, only the origin changes.

Thanks for your help.

NicDex

Anton Muhin

unread,
Sep 14, 2010, 8:06:13 AM9/14/10
to v8-u...@googlegroups.com
As Matthias says, you haven't attached the repro.

Judging from the stack trace only, are you sure you make a proper
reference to you object and it doesn't get garbage collected?

yours,
anton.

nicdex

unread,
Sep 14, 2010, 5:22:12 PM9/14/10
to v8-users
You can access the file with this url :

http://dev.nicdex.com/files/anonymous-method.cpp

Thanks,


On 14 sep, 08:06, Anton Muhin <ant...@chromium.org> wrote:
> As Matthias says, you haven't attached the repro.
>
> Judging from the stack trace only, are you sure you make a proper
> reference to you object and it doesn't get garbage collected?
>
> yours,
> anton.
>

Matthias Ernst

unread,
Sep 15, 2010, 2:08:01 AM9/15/10
to v8-u...@googlegroups.com
I cannot reproduce the crash (Mac, same v8 revision). The code looks ok to me, except you're leaking a persistent handle.

Diff:

<       MyClass* obj = static_cast<MyClass*>( 
<                       Local<External>::Cast( internalField )->Value()
<               );
---
>       MyClass* obj = static_cast<MyClass*>(External::Unwrap(internalField));
41,43c39
<       MyClass* obj = static_cast<MyClass*>( 
<                       Local<External>::Cast( internalField )->Value()
<               );
---
>       MyClass* obj = static_cast<MyClass*>(External::Unwrap(internalField));
61,64c57
<       Local<External> externalRef = External::New( cpp_object );
<       args.Holder()->SetInternalField( 0, 
<                                        Persistent<External>::New( handleScope.Close(externalRef) ) );
---
>       args.Holder()->SetInternalField( 0, External::Wrap(cpp_object));

Anton Muhin

unread,
Sep 15, 2010, 7:00:56 AM9/15/10
to v8-u...@googlegroups.com
I cannot repro it on Mac either (but I just extended test-api tests).
I could try Linux if you please. BTW, I am not sure if mingw is
supported. Could you repo the problem on any supported platform
(Win+VS, Linux + gcc, Mac + gcc)?

Overall code looks mostly fine.

One thing was noted by Matthias---Persistent handle leakage.

Overall, you can use GetPointerFromInternalField and
SetPointerToInternalField which are faster and imho easier to use (a
lot of code would just go away).

Another thing you might want to fix: it's usually a bad idea to access
internal fields on args.This(), typically you should do that on
args.Holder(): This() is the object on which the property was accessed
while Holder() points to object which was created with your custom
function. Example:

myClass = new MyClass();
o = { __proto__: myClass };

Now if you do o.gridX, args.This() should point to o while
args.Holder() should point to myClass.

In your sample This and Holder should be the same, but I wonder if
it's the case when you get a crash.

And the last: zero length arrays are prohibited. Again I think it's
just a matter of reduction, but just in case.

yours,
anton.

nicdex

unread,
Sep 15, 2010, 12:27:20 PM9/15/10
to v8-users
I'm not sure if mingw is supported officially, but it is definitively
supported in the code, since there is some #ifdef __MINGW32__ in
platform-win32.cc.

I'll try with MSVC tonight to see if it fixes the problem.

I'll keep you posted.

Thanks,
> On Wed, Sep 15, 2010 at 10:08 AM, Matthias Ernst <matth...@mernst.org> wrote:
> > I cannot reproduce the crash (Mac, same v8 revision). The code looks ok to
> > me, except you're leaking a persistent handle.
> > Diff:
> > <       MyClass* obj = static_cast<MyClass*>(
> > <                       Local<External>::Cast( internalField )->Value()
> > <               );
> > ---
> >>       MyClass* obj =
> >> static_cast<MyClass*>(External::Unwrap(internalField));
> > 41,43c39
> > <       MyClass* obj = static_cast<MyClass*>(
> > <                       Local<External>::Cast( internalField )->Value()
> > <               );
> > ---
> >>       MyClass* obj =
> >> static_cast<MyClass*>(External::Unwrap(internalField));
> > 61,64c57
> > <       Local<External> externalRef = External::New( cpp_object );
> > <
> > <       args.Holder()->SetInternalField( 0,
> > <                                        Persistent<External>::New(
> > handleScope.Close(externalRef) ) );
> > ---
> >>       args.Holder()->SetInternalField( 0, External::Wrap(cpp_object));
>

nicdex

unread,
Sep 15, 2010, 7:50:36 PM9/15/10
to v8-users
I tried with MSVC and it works.

I also tested using a setter instead of a getter in my anonymous
method and the bug doesn't reproduce, so it really seems to be limited
to using a get accessor inside an anonymous method.

I've updated the file at the same location if you want to check out
the new tests.

I still gonna submit the bug, but since it's mingw32 related it won't
get fixed soon. I guess I will have to use MSVC for now.

Thanks for your help.
Reply all
Reply to author
Forward
0 new messages