A memory error occurs when a function block is invoked during array initialization, and within that block, an array with the same name as the one currently being initialized is redefined or undefined.
function $setup() <<end
array tmp = [1]
return 2
end
array tmp = [1, $setup(), 3]
print tmp
On my macOS environment, I got the following error message:
gnuplot(92785,0x11993f5c0) malloc: *** error for object 0x7fcded43d070: pointer being realloc'd was not allocated
gnuplot(92785,0x11993f5c0) malloc: *** set a breakpoint in malloc_error_break to debug
Abort trap: 6
This is a more serious problem than one with function definitions (#2797).
Because arrays share a namespace with regular variables, the corruption also happens in a much more natural setting. It can arise for any array acces, not just initialization. I worry that a segfault from scenario below is more likely to come up, and less obvious to the user, than re-initializing a global array.
Declaring A and B as
local A = 2; local B = 3
would avoid the problem, but I think there are cases when it is reasonable for functions or function blocks to assign a value to a global variable before using it.Let's call the original post’s situation Case 1 and your situation Case 2.
These two cases are handled by different functions.
Case 1 is "parse_array_constant()", and Case 2 is "is_array_assignment()".
I created a patch to fix for Case 2 by modifing the function 'is_array_assignment()'.
In the following command,
after evaluating the right side, the fixed version detects whether the variable A is no longer an array or whether the original array pointer has been changed.
The following Case 3 also triggers a memory error:
Case.3
The patch can handle Case 3, too.
Those patches are much better than anything I have come up with so far.
I have found a 4th problem case.
I think the problem here is that the replacement array (the one that overwrites the original array) is too small to hold the fourth element of the assignment statement. This failure occurs during evaluation of
const_express()
, before the test for newvalue != oldvalue can be made.Last edit: Ethan Merritt 2025-05-20
Cases 1 and 4 seem to involve essentially the same problem. I have created a patch that addresses both.
The issue lies in how the "parse_array_constant()" function handles array initialization. In the current implementation, each right-hand-side value is evaluated and assigned directly to the destination array one by one. This can cause unexpected behavior if the destination array is modified during the evaluation.
A safer approach would be:
This patch also addresses the following case:
Case 5
Looks pretty good. I've committed all three patches to 6.1
The third patch introduced a memory leak (elements array not free'd if an error occurs). I fixed it with respect to errors in parse_array_constant(), but there's still a leak if int_error is called during evaluation of const_express().
I'm sorry.
The modification to
parse_array_constant()
in the patch 0002_parse_array_constant.patch was insufficient.An improved patch file is attached.
Please apply it after the commit [aa95c30].
There was a bug in the section that copies data from the temporary array
elements
toarray->v.value_array
. I have modified it to perform an accurate copy using the number of elements from the initializer on the right-hand side. Additionally, there was another location wherefree(elements)
was necessary when recovering from an error, so I have added that as well.Last edit: Hiroki Motoyoshi 2025-05-23
Apologies, I overlooked the deallocation of 'elements' in the event of an error in the "0002_parse_array_constatnt.patch". Thank you for fixing and applying it.
I have found another case for this issue, which is triggered by function instead of function block after Patch#827.
Case 6
The issue in Case.6 can be avoided within the
f_assign()
function by detecting variable substitution, just as we have done in previous cases.A patch to do this is attached.
However, there is a caveat regarding this patch. When using the action table for evaluation, it is not possible to obtain information about the left-hand side (i.e., the destination array) before evaluating the right-hand side. As a result, we can accurately detect changes such as an array no longer being an array, but not when one array is replaced with another. Even so, in the case of array-to-array replacement, fortunately, the execution can proceed without triggering a fatal error.
Please take a look at the following script:
Case.7
In this case, a three-element array 'A' is replaced with a one-element array 'A' inside the "$setup()" function block. Since the script then attempts to assign a value to the 2nd element of the new array, an index error occurs. If 'A' were replaced with a larger array instead, the script would continue to run without any errors.
If such behavior is acceptable, the attached patch should be sufficient to handle the Case 6 and 7.