Thursday, October 25, 2012

Third Translator Memory Issue

The memory issue reported for translator test 7 was the same message as test 6 except on a different line, which was another if statement.  Again through the process of elimination, the statement causing the error was identified to be MID$(A$ B, which is expected to produce an expected comma error at the B token.

After briefly studying this if statement, the problem was identified and is similar to the previous problem.  This if statement, in the process binary operator routine, was checking if the token (within a sub-string assignment) was not a comma.  Again, it should not have been checking the token code before checking that the code was valid (since not all token types have a code).  The B token is an identifier with no parentheses token type and code is not used.

The if statement was corrected by adding a check if the token has a table entry (and therefore a valid code) and it is not a comma.  Now all the memory issues were resolved.  I also now understand what the Conditional jump or move depends on unintialised values(s) error is indicating.  Apparently, the Analyzer (valgrind) is checking for more than just memory leaks, it is also checking when a variable is being accessed, but it hasn't been initialized, which was the case for these two if statements.

Rechecking all the tests, all the memory issues were resolved.  However, upon running the regression tests, translator test 7 was now failing.  The problem occurred with the statement above, which was now reporting an expected operator or comma error, which was wrong because with a sub-string assignments, an operator is not allowed after the string variable identifier.

The if statement was modified so that either the token does not have a table entry or the token is not a comma.  All tests now pass.  To simplify (and automate) this memory testing, a new memtest script was created, but only for Linux as it requires the valgrind program.  This new script is based on the regtest script and also checks the regression test results along with checking for memory issues.  Now back to replacing the List class with the QList class...

[commit 1d427d7d98] [commit da0014b34d]

Second Translator Memory Issue

While the first memory issue was a simple memory leak, the second issue was much more difficult to resolve.  The issue on translator test 6 was reported as a Conditional jump or move depends on unintialised values(s).  Clicking on this showed the source line and another message reporting Uninitialised value was created by a heap allocation.  The line for this message was in the token new function where the memory for the token is allocated.  Curious that the token allocation checks were not reporting any token leaks.

Through the process of elimination, the statement (out of 42) causing the error was identified to be PRINT A(TAB(10)).  Looking at the line indicated by the first message (an if statement) did not make it clear what the issue was.  So the code was stepped through with the debugger to identify the problem, which was caused by an incorrect check for the item on top of the hold stack, which happen to be the line reported with a problem.

This if statement checks if a print-only function is found in an expression, which should be reported as an error since these functions are only valid in a PRINT command.  The check is for either the current command is not a PRINT command or the token on top of the hold stack is not the null token (any other token indicates the print-only function is in a parentheses, array or function - an error).

The problem was with the null token check as it was only checking if the code of the token was not the null code.  However, not every token type has a valid code, specifically, constants, identifiers (with and without parentheses), and user defined functions (preceded by FN with and without parentheses).  This check was replaced with a call to a new token function that checks to see if the token is a null token, which first checks if the token has a table entry (and therefore a code) and then checks the code.

This corrected the problem with translator test 6.  All the expression and translator tests were rechecked with the Analyzer.  Translator test 7 was still reporting a memory issue.

First Translator Memory Leak

The first memory leak, which occurred on every expression and translator test, was easy to identify and correct as the Analyzer pointed directly to the problem.  The memory issue was reported in the translator start() function with the RPN (reverse polish notation) list allocated there.

For expression test 1, 13 blocks were reported lost, which exactly coincided with the number of test expressions.  This made it obvious that the memory allocated for the RPN list object was not being released.  In the translate input routine, after the resulting tokens in the RPN list were output, the memory allocated for each token was released.  However, the RPN list object itself was not released.

After the correction, all the expression and translator tests were rechecked with the Analyzer.  Translator tests 6 and 7 were still reporting memory issues.