Fix memory leak during collapsing in PDT.

This commit is contained in:
2023-06-06 21:13:36 +08:00
parent 82060a6403
commit a6a0ac3f9e

View File

@@ -24,8 +24,8 @@ namespace Cryville.Common.Pdt {
/// <param name="exp">The expression to evaluate.</param> /// <param name="exp">The expression to evaluate.</param>
/// <returns>Whether the evaluaton succeeded.</returns> /// <returns>Whether the evaluaton succeeded.</returns>
public bool Evaluate(PdtOperator target, PdtExpression exp) { public bool Evaluate(PdtOperator target, PdtExpression exp) {
try {
var prevFrameCount = _framecount; var prevFrameCount = _framecount;
try {
_revokepttconst = false; _revokepttconst = false;
for (var ip = exp.Instructions.First; ip != null; ip = ip.Next) for (var ip = exp.Instructions.First; ip != null; ip = ip.Next)
ip.Value.Execute(this, ref ip); ip.Value.Execute(this, ref ip);
@@ -33,12 +33,14 @@ namespace Cryville.Common.Pdt {
exp.IsConstant = exp.IsPotentialConstant = !_revokepttconst; exp.IsConstant = exp.IsPotentialConstant = !_revokepttconst;
} }
var ret = Operate(target, _framecount - prevFrameCount, true); var ret = Operate(target, _framecount - prevFrameCount, true);
for (var i = prevFrameCount; i < _framecount; i++) DiscardStack();
return ret; return ret;
} }
catch (Exception ex) { catch (Exception ex) {
throw new EvaluationFailureException(exp, ex); throw new EvaluationFailureException(exp, ex);
} }
finally {
for (var i = prevFrameCount; i < _framecount; i++) DiscardStack();
}
} }
/// <summary> /// <summary>
/// Optimizes an expression by merging its instructions. /// Optimizes an expression by merging its instructions.
@@ -205,7 +207,7 @@ namespace Cryville.Common.Pdt {
var frame = _stack[--_framecount]; var frame = _stack[--_framecount];
if (frame.Type == PdtInternalType.Error) { if (frame.Type == PdtInternalType.Error) {
_framecount -= pc - i - 1; _framecount -= pc - i - 1;
_stack[_framecount++] = new StackFrame { Type = PdtInternalType.Error, Offset = _goffset, Length = 0 }; _stack[_framecount++] = new StackFrame { Type = PdtInternalType.Error, Offset = -1, Length = 0 };
return false; return false;
} }
op.LoadOperand(new PdtVariableMemory(frame.Type, pmem + frame.Offset, frame.Length)); op.LoadOperand(new PdtVariableMemory(frame.Type, pmem + frame.Offset, frame.Length));
@@ -218,13 +220,15 @@ namespace Cryville.Common.Pdt {
internal unsafe void Collapse(int name, ref LinkedListNode<PdtInstruction> self, LinkedListNode<PdtInstruction> target) { internal unsafe void Collapse(int name, ref LinkedListNode<PdtInstruction> self, LinkedListNode<PdtInstruction> target) {
fixed (byte* pmem = _mem) { fixed (byte* pmem = _mem) {
var frame = _stack[--_framecount]; var frame = _stack[--_framecount];
_goffset -= frame.Length;
if (frame.Type == PdtInternalType.Error) { if (frame.Type == PdtInternalType.Error) {
_stack[_framecount++] = new StackFrame { Type = PdtInternalType.Error, Offset = _goffset, Length = 0 }; _stack[_framecount++] = new StackFrame { Type = PdtInternalType.Error, Offset = -1, Length = 0 };
self = target; self = target;
return; return;
} }
if (Collapse(name, new PdtVariableMemory(frame.Type, pmem + frame.Offset, frame.Length))) { if (Collapse(name, new PdtVariableMemory(frame.Type, pmem + frame.Offset, frame.Length))) {
_framecount++; _framecount++;
_goffset += frame.Length;
self = target; self = target;
} }
} }