Page 1 of 1

Memory usage grows indefinitely

Posted: 18 Nov 2023, 00:17
by asc

Code: Select all

f() {
	local a := ""
	c() {
		local b := a
	}
	cc() {
		ccc() {
			c()
		}
		ccc()
	}
	loop {
		cc()
	}
}
f()

Re: Memory usage grows indefinitely

Posted: 18 Nov 2023, 13:13
by joefiesta
excuse me if I'm ignorant here--I know almost nothing of V2--but, isn't
loop {
cc()
}


an endless loop?

Re: Memory usage grows indefinitely

Posted: 19 Nov 2023, 04:16
by just me
Just a guess:
Nested Functions wrote:By default, a nested function automatically "captures" a non-static local variable of an outer function when the following requirements are met:
  1. The outer function must refer to the variable in at least one of the following ways:
    1. By declaring it with local, or as a parameter or nested function.
    2. As the non-dynamic target of an assignment or the reference operator (&).
  2. The inner function (or a function nested inside it) must refer to the variable non-dynamically.
A nested function which has captured variables is known as a closure.

Closures wrote:A nested function is automatically a closure if it captures any non-static local variables of the outer function. The variable corresponding to the closure itself (such as activate) is also a non-static local variable, so any nested functions which refer to a closure are automatically closures.

Each call to the outer function creates new closures, distinct from any previous calls.

The closures and/or the captured variables need some memory.


By the way: Your code doesn't make sense for me.

Re: Memory usage grows indefinitely

Posted: 19 Nov 2023, 22:49
by thqby
https://github.com/AutoHotkey/AutoHotkey/blob/alpha/source/script_object.cpp#L3094

The error seems to have occurred here, FreeVars was not deleted after the function call ended.

Re: Memory usage grows indefinitely

Posted: 19 Dec 2023, 21:32
by lexikos
@thqby no, preventing FreeVars from being deleted after the function call ends is the express purpose of that code. It can't be deleted, because there is still a closure which points to it.

The error is in the section below that, which calls AddRef() on a closure in order to give it a non-zero mRefCount and thereby allow it to be deleted by Var::Free() when ~FreeVars() is called. This is supposed to be done for closures belonging to the current function (mFunc) for the reason stated in the comments. The bug is that it is also done for closures which do not belong to the current function, but to an outer function (i.e. the var is an alias to a constant). The closure is not deleted by ~FreeVars() because aliases aren't (and shouldn't be) freed, and is not deleted by the outer FreeVars due to the erroneous AddRef().

See commit 718735e8.

Re: Memory usage grows indefinitely  Topic is solved

Posted: 22 Dec 2023, 21:26
by lexikos
Fixed by v2.0.11.

Re: Memory usage grows indefinitely

Posted: 23 Dec 2023, 03:01
by V2User
@asc
Thank you for finding this bug. This kind of bug is extremely hard to find, if it happens.