www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - alias this and null reference

reply "Namespace" <rswhite4 googlemail.com> writes:
By the following code i get a normal Access Violation.
My question is: why? Even if "f0" is null, the object must be
converted to Ref and there i check if the given object is null.

Here is the Code:
[code]
// Ref.d

struct Ref(T : Object) {
private:
	T _val;

public:
	 disable
	this();

	 disable
	this(typeof(null));

	 disable
	typeof(this) opAssign(typeof(null));

	this(T val) {
		assert(val !is null);

		this._val = val;
	}

	 property
	T get() {
		return this._val;
	}
}

mixin template TRef(T) {
	 property
	Ref!(T) getRef() {
		assert(this !is null);

		return Ref!(T)(this);
	}

	alias getRef this;
}

// main.d
class Foo {
private:
	string _val;

public:
	this() { }

	void Set(string val) {
		this._val = val;
	}

	void speak() const {
		writeln(this._val);
	}

	mixin TRef!(typeof(this));
}

void with_ref(Ref!(Foo) rf) {
	rf.get.speak();
}

void without_ref(Foo f) {
	f.speak();
}

void main() {
	Foo f0; // f0 is null

	with_ref(f0); // converting with alias this. But what if f0 is
null?

	Foo f1 = new Foo();
	f1.Set("Foo!");

	with_ref(f1);
	without_ref(f1);

	readln();
}
[/code]
Apr 27 2012
next sibling parent "Simen Kjaeraas" <simen.kjaras gmail.com> writes:
On Friday, 27 April 2012 at 16:36:04 UTC, Namespace wrote:
 By the following code i get a normal Access Violation.
 My question is: why? Even if "f0" is null, the object must be
 converted to Ref and there i check if the given object is null.

When trying to convert f0 to Ref, the compiler has to look in the vtable for the getRef function. The vtable is in a nonsensical place when the class reference is null, and thus it bails out. Solution: mark getRef as final.
Apr 27 2012
prev sibling next sibling parent "Namespace" <rswhite4 googlemail.com> writes:
On Friday, 27 April 2012 at 16:49:49 UTC, Simen Kjaeraas wrote:
 On Friday, 27 April 2012 at 16:36:04 UTC, Namespace wrote:
 By the following code i get a normal Access Violation.
 My question is: why? Even if "f0" is null, the object must be
 converted to Ref and there i check if the given object is null.

When trying to convert f0 to Ref, the compiler has to look in the vtable for the getRef function. The vtable is in a nonsensical place when the class reference is null, and thus it bails out. Solution: mark getRef as final.

Great, thank you for reply, it works :). It is maybe possible, that I get another error output as "null this"? Maybe an assert or something else?
Apr 27 2012
prev sibling next sibling parent "Simen Kjaeraas" <simen.kjaras gmail.com> writes:
On Friday, 27 April 2012 at 16:57:52 UTC, Namespace wrote:
 On Friday, 27 April 2012 at 16:49:49 UTC, Simen Kjaeraas wrote:
 On Friday, 27 April 2012 at 16:36:04 UTC, Namespace wrote:
 By the following code i get a normal Access Violation.
 My question is: why? Even if "f0" is null, the object must be
 converted to Ref and there i check if the given object is 
 null.

When trying to convert f0 to Ref, the compiler has to look in the vtable for the getRef function. The vtable is in a nonsensical place when the class reference is null, and thus it bails out. Solution: mark getRef as final.

Great, thank you for reply, it works :). It is maybe possible, that I get another error output as "null this"? Maybe an assert or something else?

Now we're delving into some deep magic of the compiler. In non-release builds, the compiler adds a pre-function invariant, which is called before the function is called. This invariant contains the equivalent of assert(this !is null, "null this");, and this is what you run into. There's currently no way to get rid of this but to compile for release, in which case your own assert also goes out the window.
Apr 27 2012
prev sibling next sibling parent "Namespace" <rswhite4 googlemail.com> writes:
On Friday, 27 April 2012 at 17:08:43 UTC, Simen Kjaeraas wrote:
 On Friday, 27 April 2012 at 16:57:52 UTC, Namespace wrote:
 On Friday, 27 April 2012 at 16:49:49 UTC, Simen Kjaeraas wrote:
 On Friday, 27 April 2012 at 16:36:04 UTC, Namespace wrote:
 By the following code i get a normal Access Violation.
 My question is: why? Even if "f0" is null, the object must be
 converted to Ref and there i check if the given object is 
 null.

When trying to convert f0 to Ref, the compiler has to look in the vtable for the getRef function. The vtable is in a nonsensical place when the class reference is null, and thus it bails out. Solution: mark getRef as final.

Great, thank you for reply, it works :). It is maybe possible, that I get another error output as "null this"? Maybe an assert or something else?

Now we're delving into some deep magic of the compiler. In non-release builds, the compiler adds a pre-function invariant, which is called before the function is called. This invariant contains the equivalent of assert(this !is null, "null this");, and this is what you run into. There's currently no way to get rid of this but to compile for release, in which case your own assert also goes out the window.

I see, too bad. What could i do if i'm in release mode and will throw such error message?
Apr 27 2012
prev sibling next sibling parent "Namespace" <rswhite4 googlemail.com> writes:
I read about "collectExceptionMsg". Maybe that is a possible 
solution to catch Access Violations?
Apr 27 2012
prev sibling next sibling parent "Jonathan M Davis" <jmdavisProg gmx.com> writes:
On Friday, April 27, 2012 19:38:34 Namespace wrote:
 I read about "collectExceptionMsg". Maybe that is a possible
 solution to catch Access Violations?

Access violations / segfaults aren't exceptions. They're OS signals. You can't catch them. - Jonathan M Davis
Apr 27 2012
prev sibling next sibling parent "Namespace" <rswhite4 googlemail.com> writes:
On Friday, 27 April 2012 at 17:47:48 UTC, Jonathan M Davis wrote:
 On Friday, April 27, 2012 19:38:34 Namespace wrote:
 I read about "collectExceptionMsg". Maybe that is a possible
 solution to catch Access Violations?

Access violations / segfaults aren't exceptions. They're OS signals. You can't catch them. - Jonathan M Davis

I forget... But it should me possible to catch the "null this" message.
Apr 27 2012
prev sibling next sibling parent "Namespace" <rswhite4 googlemail.com> writes:
On Friday, 27 April 2012 at 17:51:13 UTC, Namespace wrote:
 On Friday, 27 April 2012 at 17:47:48 UTC, Jonathan M Davis 
 wrote:
 On Friday, April 27, 2012 19:38:34 Namespace wrote:
 I read about "collectExceptionMsg". Maybe that is a possible
 solution to catch Access Violations?

Access violations / segfaults aren't exceptions. They're OS signals. You can't catch them. - Jonathan M Davis

I forget... But it should me possible to catch the "null this" message.

That does what i wanted. Thank you two. :) static this() { onAssertErrorMsg(__FILE__, __LINE__, "Object is null!"); }
Apr 27 2012
prev sibling next sibling parent "Namespace" <rswhite4 googlemail.com> writes:
On Friday, 27 April 2012 at 18:01:55 UTC, Namespace wrote:
 On Friday, 27 April 2012 at 17:51:13 UTC, Namespace wrote:
 On Friday, 27 April 2012 at 17:47:48 UTC, Jonathan M Davis 
 wrote:
 On Friday, April 27, 2012 19:38:34 Namespace wrote:
 I read about "collectExceptionMsg". Maybe that is a possible
 solution to catch Access Violations?

Access violations / segfaults aren't exceptions. They're OS signals. You can't catch them. - Jonathan M Davis

I forget... But it should me possible to catch the "null this" message.

That does what i wanted. Thank you two. :) static this() { onAssertErrorMsg(__FILE__, __LINE__, "Object is null!"); }

Sorry for triple post. I was too early. I get the Message "object is null" any time, with, and without thrown asserts.
Apr 27 2012
prev sibling next sibling parent "Jonathan M Davis" <jmdavisProg gmx.com> writes:
On Friday, April 27, 2012 18:49:48 Simen Kjaeraas wrote:
 On Friday, 27 April 2012 at 16:36:04 UTC, Namespace wrote:
 By the following code i get a normal Access Violation.
 My question is: why? Even if "f0" is null, the object must be
 converted to Ref and there i check if the given object is null.

When trying to convert f0 to Ref, the compiler has to look in the vtable for the getRef function. The vtable is in a nonsensical place when the class reference is null, and thus it bails out. Solution: mark getRef as final.

How about just sticking an assertion in with_ref to verify that it's parameter is non-null? - Jonathan M Davis
Apr 27 2012
prev sibling next sibling parent "Namespace" <rswhite4 googlemail.com> writes:
On Friday, 27 April 2012 at 18:19:33 UTC, Jonathan M Davis wrote:
 On Friday, April 27, 2012 18:49:48 Simen Kjaeraas wrote:
 On Friday, 27 April 2012 at 16:36:04 UTC, Namespace wrote:
 By the following code i get a normal Access Violation.
 My question is: why? Even if "f0" is null, the object must be
 converted to Ref and there i check if the given object is 
 null.

When trying to convert f0 to Ref, the compiler has to look in the vtable for the getRef function. The vtable is in a nonsensical place when the class reference is null, and thus it bails out. Solution: mark getRef as final.

How about just sticking an assertion in with_ref to verify that it's parameter is non-null? - Jonathan M Davis

I write my Ref struct, and Adam Ruppe wrote his NotNull struct, to avoid exactly this. It's annoying to write "assert(param !is null);" every time again; a simple keyword or Ref!(Type) instead of Type is much better. But this is my opinion. That is, how I handle the "null this" assertion now: mixin template TRef(T) { final Ref!(T) getRef() in { assert(this !is null, "Object is null!"); } body { return Ref!(T)(this); } alias getRef this; } Work fine so far.
Apr 27 2012
prev sibling parent "Adam D. Ruppe" <destructionator gmail.com> writes:
On Friday, 27 April 2012 at 17:47:48 UTC, Jonathan M Davis wrote:
 Access violations / segfaults aren't exceptions. They're OS 
 signals. You can't catch them.

Actually, on Windows, access violation is a thrown Error. I don't think you should catch it, but you can. See druntime's src/rt/deh.d for the implementation. On Linux though, you can't catch the signal.
Apr 27 2012