chapel icon indicating copy to clipboard operation
chapel copied to clipboard

[Bug]: Ignoring an element from a tuple yielded from an iterator results in memory leaks

Open jabraham17 opened this issue 5 months ago • 0 comments

The following code does not correctly call the destructors for the objects allocated by the iterators and may result in leaked memory

class C {
  var id: int;
  proc deinit() {
    writeln("deinit C id=", id);
  }
}

record R {
  var id: int;
  proc deinit() {
    writeln("deinit R id=", id);
  }
}

iter foo() {
  yield (new C(1), new C(2));
  yield (new C(3), new C(4));
}

iter bar() {
  yield (new R(1), new R(2));
  yield (new R(3), new R(4));
}


for (_, x) in foo() {
  writeln(x);
}
for (_, x) in bar() {
  writeln(x);
}

The correct output is as follows

{id = 2}
deinit C id=2
deinit C id=1
{id = 4}
deinit C id=4
deinit C id=3
(id = 2)
deinit R id=2
deinit R id=1
deinit R id=2
deinit R id=1
(id = 4)
deinit R id=4
deinit R id=3
deinit R id=4
deinit R id=3

However, the deinit for the first tuple component does not get invoked. This is caused by the ignored tuple component, _. In the case of heap memory (i.e. classes or strings), then this causes memory to be leaked

Changing the bottom two loops to use a dummy variable results in correct execution:

for (dummy, x) in foo() {
  writeln(x);
}
for (dummy, x) in bar() {
  writeln(x);
}

This is related to https://github.com/chapel-lang/chapel/issues/25893, where ignoring a yielded variable results in deinit not being called

jabraham17 avatar Sep 10 '24 21:09 jabraham17