It's many megabytes of ECMAScript parser . Very hard to find out what causes access violation. Really lots of code O_O.
It's many megabytes of ECMAScript parser . Very hard to find out what causes access violation. Really lots of code O_O.
Already done, this is a stripped down version of 30k+ script that was originally crashing. If i remove or change ANY line from this extremly simple script, crash WILL NOT reproduce O_O. Crash is reproduces randomly inside for(;; ) loop - if step-by-step script code crash will not reproduce.
Qt Code:
function OnStart() { var a = [ [ 0 ] ]; for( var i = 0; i < 3; i ++ ) { for( var j = 0; j < 100; j ++ ) { "a" + a[ 0 ][ 0 ]; } } }To copy to clipboard, switch view to plain text mode
Of course a step by step crash won't reproduce if the problem is a race condition. Please insert some debugging statements in the script to see where it crashes. Also does it change anything if you just evaluate the contents of the function instead of calling the function?
Latest crash sample is a single threaded code. How race condition can occur in one thread?Of course a step by step crash won't reproduce if the problem is a race condition
Not needed, it's clear by looking at crash code that it crashes at bytecode interpreter while executing bytecode equivalent ofPlease insert some debugging statements in the script to see where it crashes
No crash if function is not called.Also does it change anything if you just evaluate the contents of the function instead of calling the function?
Is the "a" array really two dimentional (check, don't assume)?
So this works?No crash if function is not called.
Qt Code:
engine.evaluate(" var a = [ [ 0 ] ]; \ for( var i = 0; i < 3; i ++ ) \ { \ for( var j = 0; j < 100; j ++ ) \ { \ \"a\" + a[ 0 ][ 0 ]; \ } \ }");To copy to clipboard, switch view to plain text mode
In my script it is:Is the "a" array really two dimentional (check, don't assume)?
I don't have expert ECMAScript knowledge, but such definition looks surely to be two-dimensional.
Yep. And code after it crash:So this works? <evaluate skipped>
Qt Code:
for(;;) { QScriptValue oFnStart = oEngine.evaluate( "OnStart" ); Q_ASSERT( oFnStart.isFunction() ); oFnStart.call(); // Crash here in deep bytecode interpreter internals. }To copy to clipboard, switch view to plain text mode
See my last post again.
See my last post again.Yep. And code after it crash:
Qt Code:
for(;;) { QScriptValue oFnStart = oEngine.evaluate( "OnStart" ); Q_ASSERT( oFnStart.isFunction() ); oFnStart.call(); // Crash here in deep bytecode interpreter internals. }To copy to clipboard, switch view to plain text mode
Read it carefully this time.
Yes, "a" array is 2-dimentional. Calling evaluate( "a.length" ) returns 1 and calling evaluate( "a[ 0 ].length" ) also returns 1 - it's 1x1 2-dimentional array.Is the "a" array really two dimentional (check, don't assume)?
Yes, this works.So this works?
Qt Code:
engine.evaluate(" var a = [ [ 0 ] ]; \ for( var i = 0; i < 3; i ++ ) \ { \ for( var j = 0; j < 100; j ++ ) \ { \ \"a\" + a[ 0 ][ 0 ]; \ } \ }");To copy to clipboard, switch view to plain text mode
So the actual problem is with and not the script itself. Please check if the example in Qt docs for QScriptValue::call() works for you.
Original Qt call() example did not crash:
Qt Code:
QScriptEngine engine; engine.evaluate("function fullName() { return this.firstName + ' ' + this.lastName; }"); engine.evaluate("somePerson = { firstName: 'John', lastName: 'Doe' }"); QScriptValue global = engine.globalObject(); QScriptValue fullName = global.property("fullName"); QScriptValue who = global.property("somePerson"); qDebug() << fullName.call(who).toString(); // "John Doe" engine.evaluate("function cube(x) { return x * x * x; }"); QScriptValue cube = global.property("cube"); QScriptValueList args; args << 3; qDebug() << cube.call(QScriptValue(), args).toNumber(); // 27To copy to clipboard, switch view to plain text mode
After adding my script and loop to Qt call() example it crashes:
Qt Code:
QScriptEngine engine; engine.evaluate( "function fullName(){var a=[[0]]; a[0][0];}" ); QScriptValue global = engine.globalObject(); QScriptValue fullName = global.property("fullName"); for(;;) { fullName.call(); }To copy to clipboard, switch view to plain text mode
What if you add the loop to the example program? And what if you remove the loop from your program?
If i add a loop to example program it will not crash - Qt script must be exactly what i have specified.
If i remove loop from my program it will not crash.
This is some kind of weird combination of exactly specific script and a loop O_O. The script is a reduced version of my original 30+ kb script, so i think it will crash on any script large and complex enough, with a loop . On 64-bit windows only.
I don't think so. In my opinion the problem is with QScriptValue::call() and not the script itself. Add a loop around the code I have written in post #26 of this thread. If it doesn't crash then complexity of the script is irrelevant (I'd be surprised if it was relevant).
Come to think of it, what exactly do you hope to obtain with your code? What is the point of using QScriptValue::call() in this situation? Why not simply do:
Qt Code:
oEngine.evaluate( "OnStart()" );To copy to clipboard, switch view to plain text mode
I'm sure you can add code to check if OnStart() is callable at all and even if not, you will get an exception from the script where you can easily determine what happened.
By the way, what edition of Qt are you using? LGPL or commercial? They have different QtScript backends by default. The LGPL one has JIT compilation, maybe that is causing the problem.
Yes, i mean script complex enough, 64-bit, loop and call inside a loop .I don't think so. In my opinion the problem is with QScriptValue::call() and not the script itself.
It will crash . Crash is inside QtScript code execution. I have carefully tested all ways to invoke a script function: evaluate( "foo" ).call(), globalObject().getProperty( "foo" ).call(), evaluate( "foo()" ) and connecting signals to slots inside of script. Anything will crash on QtScript execution if script is from my example, it's execution is inside a loop and windows is 64-bit .Why not simply do: oEngine.evaluate( "OnStart()" );
I'm using LGPL version. Is it possible to disable JIT compilation in LGPL version?By the way, what edition of Qt are you using? LGPL or commercial? They have different QtScript backends by default. The LGPL one has JIT compilation, maybe that is causing the problem.
Thanks. What i need to do in order to rebuild QtScript with different back-end? Some defines, nmake targets or what?You can rebuild QtScript with the other backend and see if it helps.
To disable JIT, issue:
configure -no-javascript-jit
and rebuild Qt.
I'm not sure how to change the backend, you have to search for it in the docs, I'm sure I have seen it somewhere (maybe it was somewhere in the Internet? At Qt Labs maybe?). Probably issuing -no-webkit would do the trick but that's a bit of a drastic method of doing this.
Windows version of 'configure' don't support '-no-javascript-jit'. The only 'configure' key on windows i can see that is related to QtScript subsystem are '-script' and '-noscript'.To disable JIT, issue:
configure -no-javascript-jit
and rebuild Qt.
Bookmarks