我在 codewars 上做 Tiny Three-Pass Compiler ,我在節點 v.10 上一直收到錯誤說`
FATAL ERROR: CALL_AND_RETRY_LAST 分配失敗 - JavaScript heap out of memory Aborted (core dumped) <--- 最近幾次 GC --->
[19:0x5578df6e1f80] 6093 ms:Mark-sweep 580.2 (592.5) -> 580.2 (584.5) MB,1501.0 / 0.0 ms(平均 mu = 0.282,當前 mu = 0.000)請求舊空間中的最后手段 GC [19:0x5578df6e1f80] 6285 ms:Mark-sweep 580.2 (584.5) -> 580.2 (584.5) MB,191.9 / 0.0 ms(平均 mu = 0.243,當前 mu = 0.000)請求舊空間中的最后手段 GC
<--- JS 堆疊跟蹤 --->
==== JS 堆疊跟蹤 ==========================================
0: ExitFrame [pc: 0x3dbb90e5be1d] Security context: 0x3dd3dcdf3419 <JSObject> 1: /* anonymous */ [0x3dd3dcdcb241] [/home/codewarrior/node/test.js:~48][pc=0x3dbb90efc9ce](this=0x3d354a868c89 ,program=0x1344e3ade909 <String[47]: [ xyz ] ( 2 3 x
- 5 y - 3 z ) / (1 3 2 2)>) 2: /匿名 */ [0x3d354a8463c9] [/home/codewarrior/node/test.js:214] [bytecode=0x3dd3dcdce859 offset=90](this =0x3d354...`
在節點 v.8 上,我收到此錯誤: `
致命錯誤:CALL_AND_RETRY_LAST 分配失敗 - JavaScript 堆記憶體不足中止(核心轉儲)`
我目前使用的代碼是:
function isNumber (token){
return !isNaN(token);
}
function isOperator(token){
return "*/ -".indexOf(token) !== -1;
}
function Compiler () {};
Compiler.prototype.compile = function (program) {
return this.pass3(this.pass2(this.pass1(program)));
};
Compiler.prototype.tokenize = function (program) {
// Turn a program string into an array of tokens. Each token
// is either '[', ']', '(', ')', ' ', '-', '*', '/', a variable
// name or a number (as a string)
var regex = /\s*([- */\(\)\[\]]|[A-Za-z] |[0-9] )\s*/g;
return program.replace(regex, ":$1").substring(1).split(':').map( function (tok) {
return isNaN(tok) ? tok : tok|0;
});
};
Compiler.prototype.pass1 = function (program) {
var tokens = this.tokenize(program);
function getNextToken(){
token = tokens.shift();
}
function precedenceIsNotGreater(o1, o2){
var precedences = {
'/' : 4,
'*' : 3,
' ' : 2,
'-' : 1,
}
return precedences[o1] <= precedences[o2];
}
var token ;
var outputQueue = [];
var operatorStack = [];
var args = [];
do{
getNextToken()
if(token === '['){
for(getNextToken(); token !== ']'; getNextToken()){
args.push(token);
}
}else if(isNumber(token) || args.includes(token)){
outputQueue.push(token);
}else if(isOperator(token)){
var o1 = token;
for(var o2 = operatorStack[operatorStack.length-1]; operatorStack.length && isOperator(o2) && precedenceIsNotGreater(o1, o2); o2 = operatorStack[operatorStack.length -1]){
outputQueue.push(token);
}
operatorStack.push(o1);
}else if(token === '('){
operatorStack.push(token);
} else if(token === ')'){
for(var nextOperator = operatorStack[operatorStack.length -1]; operatorStack.length && nextOperator !== '('; nextOperator = operatorStack[operatorStack.length-1]){
outputQueue.push(operatorStack.pop())
}
operatorStack.pop()
}
} while(tokens.length);
while(operatorStack.length){
outputQueue.push(operatorStack.pop())
}
var output;
function getNextOutput(){
output = outputQueue.pop();
}
function buildAst(outputQueue) {
getNextOutput();
var node = {};
if(isNumber(output)){
node.op = 'imm';
node.n = output;
} else if(args.includes(output)){
node.op = 'arg';
node.n = args.indexOf(output);
} else if(isOperator(output)){
node.op = output;
var b = buildAst(outputQueue);
var a = buildAst(outputQueue);
node.a = a;
node.b = b;
}
return node;
}
return buildAst(outputQueue);
};
Compiler.prototype.pass2 = function (ast) {
function reduceTree(ast) {
if(ast.op === 'imm' || ast.op === 'arg') {
return ast;
}
ast.a = reduceTree(ast.a);
ast.b = reduceTree(ast.b);
if(ast.a.op === 'imm' && ast.b.op === 'imm'){
var n = Function("return " '' ast.a.n ast.op ast.b.n)();
return{ op: 'imm', n: n}
}
return ast;
}
return reduceTree(ast)
};
Compiler.prototype.pass3 = function (ast) {
var operatorMap = {
' ' : 'AD',
'-' : 'SU',
'*' : 'MU',
'/' : 'DI',
}
var operationDepths = {};
var maxDepth = -Infinity;
function markDepth (ast, depth = 0){
if(ast.a && ast.b){
maxDepth = Math.max(maxDepth, depth);
if(!operationDepths[depth]){
operationDepths[depth] = [];
}
operationDepths[depth].push(ast);
markDepth(ast.a, depth 1);
markDepth(ast.b, depth 1);
}
}
markDepth(ast);
var asm = [];
var currentDepth = maxDepth;
while(currentDepth >= 0){
currentDepthOperations = operationDepths[currentDepth];
while(currentDepthOperations.length){
var currentOperation = currentDepthOperations.shift();
if(currentOperation.b.op === 'imm'){
asm.push('IM ' currentOperation.b.n);
}else if(currentOperation.b.op === 'arg'){
asm.push('AR ' currentOperation.b.n)
}else{
asm.push('PO')
}
asm.push('SW')
if(currentOperation.a.aop === 'imm'){
asm.push('IM ' currentOperation.a.n)
}else if(currentOperation.a.op === 'arg') {
asm.push('AR ' currentOperation.a.n)
}else{
asm.push('PO')
}
asm.push(operatorMap[currentOperation.op]);
asm.push('PU')
}
currentDepth--;
}
return asm;
};
如果有人可以提供幫助,那就太好了!提前致謝。
uj5u.com熱心網友回復:
堆溢位的原因是你這里有一個無限回圈:
for(var o2 = operatorStack[operatorStack.length-1]; operatorStack.length && isOperator(o2) && precedenceIsNotGreater(o1, o2); o2 = operatorStack[operatorStack.length -1]){
if (count-- < 0) throw "too many iterations second for";
outputQueue.push(token);
}
如果該回圈進入時其回圈條件為真,則該回圈條件將始終保持為真。這是因為它不會從該堆疊中彈出任何內容。最終,不斷增長的outputQueue記憶體將占用所有可用的堆記憶體。
更正是替換這個:
outputQueue.push(token);
和:
outputQueue.push(operatorStack.pop());
免責宣告:我沒有檢查這個相當大的代碼塊中的任何其他問題。這只會解決您遇到的錯誤及其原因。
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/508643.html
標籤:javascript
上一篇:將陣列物件值推送到新陣列中
