Forum Discussion
OLEONTYEV
12 years agoOccasional Contributor
Now, the report of my experience.
The general code in our tests looks tike that:
procedure SomeParser(xmlNode : OleVariant);
var i, node, ...
begin
try
// ... some code
for i := 0 to xmlNode.childNodes.length - 1 do // <-- here it breaks
begin
node := xmlNode.childNodes;
// ... some code
SomeParser(node); // <-- recursion
// ... some code
end;
except
Log.Error('Exception', ExceptionMessage)
end;
end;
In TC7, it works fine.
In TC9, at the second level of recursion, it suddently breaks when we enter the FOR loop. It throws an exception without any additional message.
The problem was localized this way:
Let's create a project that contains one small script:
procedure RecurrentStuff1(depth : integer);
begin
try
Log.Message('Entering level ' + IntToStr(depth));
if depth > 0 then
begin
Log.Message('Calling stuff');
RecurrentStuff1(depth - 1);
Log.Message('Call finished at level ' + IntToStr(depth));
end;
Log.Message('Leaving level ' + IntToStr(depth));
except
Log.Error('Exception', ExceptionMessage)
end;
end;
procedure Main;
begin
RecurrentStuff1(3);
end;
In the log there are messages:
(i) Entering level 3
(i) Calling stuff
(i) Entering level 2
(i) Calling stuff
.....
(i) Leaving level 2
(X) DelphiScript runtime error
Stack is empty
At least, it goes through some levels. It tells what happened and doesn't break at the 2nd level, unlike in my real projects.
It can be one of 2 issues:
1) because of referencing the local variable;
2) because of the loop itself.
Let's check it to see what's happening in the real projects.
procedure RecurrentStuff2(depth : integer);
var i : integer;
begin
try
Log.Message('Entering level ' + IntToStr(depth));
i := -1;
Log.Message('i has been referenced');
for i := 1 to depth do
begin
Log.Message('Iteration #' + IntToStr(i));
RecurrentStuff2(depth - 1);
Log.Message('Iteration #' + IntToStr(i) + ' at level ' + IntToStr(depth) + ' completed');
end;
Log.Message('Leaving level ' + IntToStr(depth));
except
Log.Error('Exception', ExceptionMessage)
end;
end;
Log messages are:
(i) Entering level 3
(i) i has been referenced
(i) Iteration #1
(i) Entering level 2
(i) i has been referenced
(X) Exception
(i) Iteration #1 at level 3 completed
.....
So, it has nothing to do with referencing i variable, but it breaks when entering the FOR loop. And exceptions have no message.
I tried to find a workaround and used "while true" loop, issuing a break from inside. It really walked through all levels of recursion, but it issued the same runtime error "Stack is empty" in the end.
A funny thing, that in JScript it all works fine, no fails in TC/TE v.9! But we can't just create one part of the suite in DelphiScript and another in JScript, we need to translate all the suite then.
The general code in our tests looks tike that:
procedure SomeParser(xmlNode : OleVariant);
var i, node, ...
begin
try
// ... some code
for i := 0 to xmlNode.childNodes.length - 1 do // <-- here it breaks
begin
node := xmlNode.childNodes;
// ... some code
SomeParser(node); // <-- recursion
// ... some code
end;
except
Log.Error('Exception', ExceptionMessage)
end;
end;
In TC7, it works fine.
In TC9, at the second level of recursion, it suddently breaks when we enter the FOR loop. It throws an exception without any additional message.
The problem was localized this way:
Let's create a project that contains one small script:
procedure RecurrentStuff1(depth : integer);
begin
try
Log.Message('Entering level ' + IntToStr(depth));
if depth > 0 then
begin
Log.Message('Calling stuff');
RecurrentStuff1(depth - 1);
Log.Message('Call finished at level ' + IntToStr(depth));
end;
Log.Message('Leaving level ' + IntToStr(depth));
except
Log.Error('Exception', ExceptionMessage)
end;
end;
procedure Main;
begin
RecurrentStuff1(3);
end;
In the log there are messages:
(i) Entering level 3
(i) Calling stuff
(i) Entering level 2
(i) Calling stuff
.....
(i) Leaving level 2
(X) DelphiScript runtime error
Stack is empty
At least, it goes through some levels. It tells what happened and doesn't break at the 2nd level, unlike in my real projects.
It can be one of 2 issues:
1) because of referencing the local variable;
2) because of the loop itself.
Let's check it to see what's happening in the real projects.
procedure RecurrentStuff2(depth : integer);
var i : integer;
begin
try
Log.Message('Entering level ' + IntToStr(depth));
i := -1;
Log.Message('i has been referenced');
for i := 1 to depth do
begin
Log.Message('Iteration #' + IntToStr(i));
RecurrentStuff2(depth - 1);
Log.Message('Iteration #' + IntToStr(i) + ' at level ' + IntToStr(depth) + ' completed');
end;
Log.Message('Leaving level ' + IntToStr(depth));
except
Log.Error('Exception', ExceptionMessage)
end;
end;
Log messages are:
(i) Entering level 3
(i) i has been referenced
(i) Iteration #1
(i) Entering level 2
(i) i has been referenced
(X) Exception
(i) Iteration #1 at level 3 completed
.....
So, it has nothing to do with referencing i variable, but it breaks when entering the FOR loop. And exceptions have no message.
I tried to find a workaround and used "while true" loop, issuing a break from inside. It really walked through all levels of recursion, but it issued the same runtime error "Stack is empty" in the end.
A funny thing, that in JScript it all works fine, no fails in TC/TE v.9! But we can't just create one part of the suite in DelphiScript and another in JScript, we need to translate all the suite then.
Related Content
Recent Discussions
- 5 days ago
- 5 days ago