digitalmars.D.learn - segfault in invariant { assert(super); }
- SimonN (40/40) Dec 19 2015 Hi,
- Steven Schveighoffer (13/47) Dec 21 2015 Yes. assert calls the virtual invariant function, which in the case of
- SimonN (17/25) Dec 22 2015 Thanks for the reply! Yeah, this helps for a clearer picture of
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 _D9invariant12_d_invariantFC6ObjectZv () (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? 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.) -- Simon
Dec 19 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 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
Dec 21 2015
On Monday, 21 December 2015 at 20:29:14 UTC, Steven Schveighoffer wrote: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).Thanks for the reply! Yeah, this helps for a clearer picture of what's happening. In particular, even though all invariants of a class hierarchy are tested instead of only the most-subclassed-one, triggering the invariant check remains virtual. I didn't know that. Even if Base.f() is const, it's not allowed inside Derived.invariant(). This is again understandable: By OOP principles, Derived shouldn't impose further restrictions on Base than what Base imposes on itself already.2) The example is a dustmite'd version of this:It seems like something you shouldn't do. AFAIK, invariant should not call any public functions on your existing class.(good idea to file an enhancement report).For that, I was trying earlier today to find the exact instances of when there is a warning, and when there is not. I didn't get warnings to come up consistently. (Even the case I described in question 2 doens't always give a warning.) I'd have to take a look at this some time again. -- Simon
Dec 22 2015