www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Re: Null references redux

reply bearophile <bearophileHUGS lycos.com> writes:
If nonnull class references are added to D, then it can be good to add nonnull
struct pointers too, to avoid similar bugs.

(In C# for a struct you define a "default" one, that gets used by the compiler
as the default one when the struct reference is null).

Bye,
bearophile
Sep 30 2009
next sibling parent reply Max Samukha <spambox d-coding.com> writes:
On Wed, 30 Sep 2009 08:53:57 -0400, bearophile
<bearophileHUGS lycos.com> wrote:

If nonnull class references are added to D, then it can be good to add nonnull
struct pointers too, to avoid similar bugs.

(In C# for a struct you define a "default" one, that gets used by the compiler
as the default one when the struct reference is null).

Bye,
bearophile

Don't get confused by 'new' in struct initializers. Structs in C# are value types. You can box them, use pointers to them in 'unsafe' context but you can't directly allocate them on heap. So there is no nullable references to structs. When you do: struct S { public int x; } S s = new S(); // x is default initialized to 0 the struct is still allocated on stack and passed by value. S s; s.x = 1; //error, struct is not initialized BTW, C# does have null-initialization problems regardless of flow control. One example: struct S { public Object obj; } S s = new S(); s.obj.ToString(); // null-reference exception;
Sep 30 2009
next sibling parent Max Samukha <spambox d-coding.com> writes:
On Wed, 30 Sep 2009 18:26:20 +0300, Max Samukha <spambox d-coding.com>
wrote:

On Wed, 30 Sep 2009 08:53:57 -0400, bearophile
<bearophileHUGS lycos.com> wrote:

If nonnull class references are added to D, then it can be good to add nonnull
struct pointers too, to avoid similar bugs.

(In C# for a struct you define a "default" one, that gets used by the compiler
as the default one when the struct reference is null).

Bye,
bearophile

Don't get confused by 'new' in struct initializers. Structs in C# are value types. You can box them, use pointers to them in 'unsafe' context but you can't directly allocate them on heap. So there is no nullable references to structs. When you do: struct S { public int x; } S s = new S(); // x is default initialized to 0

Ok. I have rechecked this one and it appears that you don't have to initialize a struct if it is a POD (Microsoft names such structs 'unmanaged', of course) or you don't access fields that are references. For example: struct S { public int x; public Object obj; } S s; s.x = 1; // ok, we can get away without initialization for now s.obj.ToString(); // compile-time error
Sep 30 2009
prev sibling next sibling parent reply bearophile <bearophileHUGS lycos.com> writes:
Max Samukha:

 Don't get confused by 'new' in struct initializers. Structs in C# are
 value types.

Yes, you are right. But in D structs can be allocated on the heap too, so I think having optional nonnull struct pointers can be useful. The syntax and usage is similar to normal struct pointers. Bye, bearophile
Sep 30 2009
next sibling parent reply Michel Fortin <michel.fortin michelf.com> writes:
On 2009-09-30 15:30:02 -0400, "Denis Koroskin" <2korden gmail.com> said:

 Note that C stdlib (and other libraries/bindings) will need to be 
 updated  to reflect changes, e.g.
 
 extern(C) void*? malloc(size_t size); // may return null!
 
 which is great because it will provide additional safety. I've seen 
 quite  a lot of code that don't test returned value against null (which 
 is a  mistake, I believe).

Which makes me think of this: pointers being non-nullable by default will make it easy to make mistakes when writing C bindings. A programmer might see this C declaration: void* malloc(size_t size); and naively translate it to D like this: extern(C) void* malloc(size_t size); without noticing the change in semantics. For pointer arguments it's not much of a problem: the worse that can happen is that it blocks you from passing a null value when you should (in which case you can update the bindings). For a return value it's more troublesome because you're implicitly adding a promise that the function will not return null, and you might not realize it's wrong until it does indeed return null and your program crashes with a segfault. Not that I think it's worth bothering too much, but it's something to keep in mind. -- Michel Fortin michel.fortin michelf.com http://michelf.com/
Sep 30 2009
parent bearophile <bearophileHUGS lycos.com> writes:
Michel Fortin:

 For a return value it's 
 more troublesome because you're implicitly adding a promise that the 
 function will not return null, and you might not realize it's wrong 
 until it does indeed return null and your program crashes with a 
 segfault.

I see. It's a matter of how much you value safety in your language. If you want a safer language, like Cyclone tries to be, the compiler may disallow function signatures like: extern(C) void* foo(size_t size); And force to use: extern(C) void*? foo(size_t size); Because the D compiler can't be sure that foo() returns a nonnull. In such situation you may just use the function like that, that returns a nullable pointer. This gives no overhead, and no safety. Or you can add a bit of overhead and use something like an enforce (or an if) to create a nonnullable pointer from the nullable result of foo(). Finally if you are very sure your C function never returns a null, and you really want to use a nonnullable pointer around in your code, but you don't want to pay for the little null test in the D code, then you hard cast the nullable pointer to a nonnullable one, but I hope this is done in really uncommon situations. I think this may solve the problem in a good enough way. Bye, bearophile
Sep 30 2009
prev sibling next sibling parent reply Yigal Chripun <yigal100 gmail.com> writes:
On 30/09/2009 18:44, bearophile wrote:
 Max Samukha:

 Don't get confused by 'new' in struct initializers. Structs in C# are
 value types.

Yes, you are right. But in D structs can be allocated on the heap too, so I think having optional nonnull struct pointers can be useful. The syntax and usage is similar to normal struct pointers. Bye, bearophile

why not just use references with structs? struct S { ... } S* sPtr = new S; S sRef = *sPtr; // non-null ref there is no need for non-null pointers.
Sep 30 2009
parent Jeremie Pelletier <jeremiep gmail.com> writes:
Yigal Chripun wrote:
 On 30/09/2009 18:44, bearophile wrote:
 Max Samukha:

 Don't get confused by 'new' in struct initializers. Structs in C# are
 value types.

Yes, you are right. But in D structs can be allocated on the heap too, so I think having optional nonnull struct pointers can be useful. The syntax and usage is similar to normal struct pointers. Bye, bearophile

why not just use references with structs? struct S { ... } S* sPtr = new S; S sRef = *sPtr; // non-null ref there is no need for non-null pointers.

Because sRef wouldn't be a reference but a copy.
Sep 30 2009
prev sibling parent Justin <no spam.com> writes:
bearophile Wrote:

 Max Samukha:
 
 Don't get confused by 'new' in struct initializers. Structs in C# are
 value types.

Yes, you are right. But in D structs can be allocated on the heap too, so I think having optional nonnull struct pointers can be useful. The syntax and usage is similar to normal struct pointers. Bye, bearophile

AYK, in C++ structs are just classes with public protection (for members) by default, or, if you like, classes are just structs with private protection (for members) by default. Other than protection rules there aint any *useful* difference semantically and you can have pointers or references to both. To a certain extent Bjarne would have done C++ a favour by either (1) not introducing "class" as a separate language entity and simply resigning to #define class struct and adding the OO the features to struct, or (2), instead of bleeding OO features into structs, heeding "teacher, teacher leave the struct alone" and introducing "class" as the clean addition that C++ brought to C. With D, the designer has made some rather brilliant distinction between classes and structs in terms of value vs reference. In doing so he has sorted out the dot (.) vs arrow (->) mess that is the infamous signature of C++. Quoting from the D spec: "Structs and unions are meant as simple aggregations of data, or as a way to paint a data structure over hardware or an external type. External types can be defined by the operating system API, or by a file format. Object oriented features are provided with the class data type." I think it would be a billion dollar mistake to make the last sentence in that quote obsolete. But, if people insist, then let's be consistent and apply the same logic (re optional nonnull pointers being useful) to unions as well (and, for that matter, to anything that can be pointed to). Ahggg, shock horror. But then again, out of the shock and horror, maybe something beautiful can evolve. Cheers -- Justin Johansson
Oct 02 2009
prev sibling parent Max Samukha <spambox d-coding.com> writes:
On Wed, 30 Sep 2009 18:26:20 +0300, Max Samukha <spambox d-coding.com>
wrote:

BTW, C# does have null-initialization problems regardless of flow
control.

I'll probably never learn to proof-read my opuses. It should have been "flow analysis".
Sep 30 2009
prev sibling next sibling parent Jarrett Billingsley <jarrett.billingsley gmail.com> writes:
On Wed, Sep 30, 2009 at 12:44 PM, bearophile <bearophileHUGS lycos.com> wrote:
 Max Samukha:

 Don't get confused by 'new' in struct initializers. Structs in C# are
 value types.

Yes, you are right. But in D structs can be allocated on the heap too, so I think having optional nonnull struct pointers can be useful. The syntax and usage is similar to normal struct pointers.

I don't know why a struct pointer would be different than any other pointer. That is, you'd have S* and S*? as well as int* and int*?.
Sep 30 2009
prev sibling next sibling parent "Denis Koroskin" <2korden gmail.com> writes:
On Wed, 30 Sep 2009 23:08:40 +0400, Jarrett Billingsley  
<jarrett.billingsley gmail.com> wrote:

 On Wed, Sep 30, 2009 at 12:44 PM, bearophile <bearophileHUGS lycos.com>  
 wrote:
 Max Samukha:

 Don't get confused by 'new' in struct initializers. Structs in C# are
 value types.

Yes, you are right. But in D structs can be allocated on the heap too, so I think having optional nonnull struct pointers can be useful. The syntax and usage is similar to normal struct pointers.

I don't know why a struct pointer would be different than any other pointer. That is, you'd have S* and S*? as well as int* and int*?.

Note that C stdlib (and other libraries/bindings) will need to be updated to reflect changes, e.g. extern(C) void*? malloc(size_t size); // may return null! which is great because it will provide additional safety. I've seen quite a lot of code that don't test returned value against null (which is a mistake, I believe).
Sep 30 2009
prev sibling parent Jarrett Billingsley <jarrett.billingsley gmail.com> writes:
On Wed, Sep 30, 2009 at 3:30 PM, Denis Koroskin <2korden gmail.com> wrote:

 Note that C stdlib (and other libraries/bindings) will need to be updated to
 reflect changes, e.g.

 extern(C) void*? malloc(size_t size); // may return null!

 which is great because it will provide additional safety. I've seen quite a
 lot of code that don't test returned value against null (which is a mistake,
 I believe).

Wonderful. Don't you love self-documenting code that forces you to use it correctly? :P
Sep 30 2009