segfault in invariant { assert(super); }

Steven Schveighoffer via Digitalmars-d-learn digitalmars-d-learn at puremagic.com
Mon Dec 21 12:29:14 PST 2015


On 12/19/15 11:01 PM, SimonN wrote:
> Hi,
>
> the following code compiles fine, then segfaults upon running.
>
>      class Base {
>          this(int) { }
>      }
>
>      class Derived : Base {
>          this(int a) { super(a); }
>          invariant() { assert (super); }
>      }
>
>      void main()
>      {
>          new Derived(5);
>      }
>
> Tested both with dmd 2.069.2 on Linux 64-bit, and on dpaste's dmd 2.069.1:
>
>      http://dpaste.dzfl.pl/4b9475c668f1
>
> Backtrace on my home machine:
>
>      Program received signal SIGSEGV, Segmentation fault.
>      0x00000000004246a5 in _D9invariant12_d_invariantFC6ObjectZv ()
>      (gdb) bt
>      #0  0x00000000004246a5 in _D9invariant12_d_invariantFC6ObjectZv ()
>      #1  0x0000000000647bf0 in _D3app7Derived6__initZ ()
>      #2  0x00007fffff7ff030 in ?? ()
>      #3  0x000000000042301f in _D3app7Derived12__invariant1MxFZv (this=0x0)
>          at source/app.d:7
>      Backtrace stopped: previous frame inner to this frame (corrupt stack?)
>
> So, looks like endless recursion inside the invairant.
>
> Questions:
>
> 1) Is this recursion expected?

Yes. assert calls the virtual invariant function, which in the case of 
super is equivalent to this. So you are essentially calling assert(this).

> 2) The example is a dustmite'd version of this: I have a public final
> method Base.f(), and the compiler won't let me call f() in Derived's
> invariant. This is understandable, because f() is also a public method
> of Derived. However, I can call super.f() explicitly in Derived's
> invariant, with no compiler error. Is that expected to work, or should
> it lead to a similar segfault? (I get the segfault.)

It seems like something you shouldn't do. AFAIK, invariant should not 
call any public functions on your existing class. It would make sense 
that super.f() should be disallowed if f() is disallowed (good idea to 
file an enhancement report).

But the compiler can't prevent all issues here. All you need to do is 
obscure that the object you are asserting is 'this', and you can achieve 
the behavior.

The runtime could potentially use a gate to prevent recursive calls, 
though I think the compiler would have to do this.

-Steve


More information about the Digitalmars-d-learn mailing list