Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

extra dtor call with typed variadic argument (or missing postblit) #17822

Open
dlangBugzillaToGithub opened this issue Dec 4, 2017 · 1 comment
Labels
Arch:x86 Issues specific to x86 P3 Severity:normal

Comments

@dlangBugzillaToGithub
Copy link

Ketmar Dark reported this on 2017-12-04T06:57:48Z

Transferred from https://issues.dlang.org/show_bug.cgi?id=18029

CC List

  • Ketmar Dark

Description

the following code failing the assertion:

===
int rc = 0;

struct S {
  int n;
  this (int na) { ++rc; n = na; import core.stdc.stdio; printf("ctor for (n=%d)
", n); }
  this (this) { if (n) ++rc; import core.stdc.stdio; printf("postblit for (n=%d)
", n); }
  ~this () { if (n) --rc; import core.stdc.stdio; printf("dtor for (n=%d)
", n); n = 0; }
}

void test0 (S[] vals...) {
  vals[0] = S.init; //(1) this causes the bug
}

void test1 () {
  auto a0 = S(1);
  test0(a0);
}

void main () {
  test1();
  assert(rc == 0);
}
===

`dtor for (n=1)` is called twice, but only if (1) is not commented. comment out (1), and the bug is gone.

*technically* calling dtor on already destructed struct is not a bug. but IRL it will ruin any reference counting scheme.

tbh, i don't know how to fix this... let's say "corner case" without loosing performance.

also, i dont' know why `a0` isn't cleared by `vals[0] = S.init;`. i thought that typed vararg just creates a slice of program stack, and assigning `.init` to `vals` member should clear `a0`. either that, or compiler should call postblit for each typed vararg member (please, no! ;-).

so, this can be "missing postblit call" case too. i put both in subj until we'll decide what should be done in this case.

please note that i'm clearing `n` in dtor, so calling dtor on already "destroyed" struct should not be disasterous. but somehow `a0` is not cleared.
@dlangBugzillaToGithub
Copy link
Author

ilya.yanok commented on 2024-11-20T14:28:22Z

The arguments are most definitely copied, one can easily see that by taking the addresses of `vals[0]` and `a0` respectively. The spec is also pretty clear that the contents of the array is invalid after the function exits, see 5. here: https://docarchives.dlang.io/v2.076.0/spec/function.html#typesafe_variadic_functions

So, that a0 remains unchanged is not really a mystery.

It is weird though, that neither copy constructor nor postblit is called (I tried adding a copy constructor), probably some kind of optimization? But should we require typed varargs to always be const then?

Then, the default opAssign calls the destructor on the lvalue being assigned. That seems to be correct, but since the value was never constructed, this causes a disparity in constructor/destructor calls you observe.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Arch:x86 Issues specific to x86 P3 Severity:normal
Projects
None yet
Development

No branches or pull requests

1 participant