View mode: basic / threaded / horizontal-split · Log in · Help
September 27, 2009
Re: Null references redux
On 27-9-2009 9:20, Walter Bright wrote:
> language_fan wrote:
>> The idea behind non-nullable types and other contracts is to catch
>> these errors on compile time. Sure, the code is a bit harder to write,
>> but it is safe and never segfaults. The idea is to minimize the amount
>> of runtime errors of all sorts. That's also how other features of
>> statically typed languages work.
>
>
> I certainly agree that catching errors at compile time is preferable by
> far. Where I disagree is the notion that non-nullable types achieve
> this. I've argued extensively here that they hide errors, not fix them.
>
> Also, by "safe" I presume you mean "memory safe" which means free of
> memory corruption. Null pointer exceptions are memory safe. A null
> pointer could be caused by memory corruption, but it cannot *cause*
> memory corruption.

// t.d
void main()
{
   int* a;
   a[20000] = 2;
}

[C:\Users\Lionello] dmd -run t.d

[C:\Users\Lionello]

This code passes on Vista. Granted, needs a big enough offset and some 
luck, but indexing null will never be secure in the current flat memory 
models.

L.
September 28, 2009
Re: Null references redux
Lutger:

> First, there is a huge demand for programmers, so much that even I got hired 
> in this time of crisis ;) Good programmers don't suddenly fall from the 
> skies apparently. 

This is the nicest thing I've read this week. Thank you very much :-)
Biologists aren't that lucky, apparently.

Bye,
bearophile
September 28, 2009
Re: Null references redux
"Jeremie Pelletier" <jeremiep@gmail.com> wrote in message 
news:h9mmre$1i8j$1@digitalmars.com...
> Ary Borenszweig wrote:
>>
>> Object is not-nullable, Object? (or whatever syntax you like) is 
>> nullable. So that line is a compile-time error: you can't cast a null to 
>> an Object (because Object *can't* be null).
>>
>
> union A {
> Object foo;
> Object? bar;
> }
>
> Give me a type system, and I will find backdoors :)
>

Unions are nothing more than an alternate syntax for a reinterpret cast. And 
it's an arguably worse syntax because unlike casts, uses of it are 
indistinguishable from normal safe code, there's nothing to grep for. As 
such, unions should never be considered any more safe than cast(x)y. The 
following is just as dangerous as your example above and doesn't even touch 
the issue of nullability/non-nulability:

union A {
int foo;
float bar;
}
September 28, 2009
Re: Null references redux
On Mon, 28 Sep 2009 01:31:44 +0400, Jeremie Pelletier <jeremiep@gmail.com>  
wrote:

> Andrei Alexandrescu wrote:
>> Jeremie Pelletier wrote:
>>>> Is this Linux specific? what about other *nix systems, like BSD and  
>>>> solaris?
>>>
>>> Signal handler are standard to most *nix platforms since they're part  
>>> of the posix C standard libraries, maybe some platforms will require a  
>>> special handling but nothing impossible to do.
>>  Let me write a message on behalf of Sean Kelly. He wrote that to  
>> Walter and myself this morning, then I suggested him to post it but  
>> probably he is off email for a short while. Hopefully the community  
>> will find a solution to the issue he's raising. Let me post this:
>>  ===================
>> Sean Kelly wrote:
>>  There's one minor problem with his code.  It's not safe to throw an  
>> exception from a signal handler.  Here's a quote from the POSIX spec at  
>> opengroup.org:
>>  "In order to prevent errors arising from interrupting non-reentrant  
>> function calls, applications should protect calls to these functions  
>> either by blocking the appropriate signals or through the use of some  
>> programmatic semaphore (see semget() , sem_init() , sem_open() , and so  
>> on). Note in particular that even the "safe" functions may modify  
>> errno; the signal-catching function, if not executing as an independent  
>> thread, may want to save and restore its value. Naturally, the same  
>> principles apply to the reentrancy of application routines and  
>> asynchronous data access. Note thatlongjmp() and siglongjmp() are not  
>> in the list of reentrant functions. This is because the code executing  
>> after longjmp() and siglongjmp() can call any unsafe functions with the  
>> same danger as calling those unsafe functions directly from the signal  
>> handler. Applications that use longjmp() andsiglongjmp() from within  
>> signal handlers require rigorous protection in order to be portable."
>>  If this were an acceptable approach it would have been in druntime  
>> ages ago :-)
>> ===================
>>    Andrei
>
> Yes but the segfault signal handler is not made to design code that can  
> live with these exceptions, its just a feature to allow segfaults to be  
> sent to the crash handler to get a backtrace dump. Even on windows while  
> you can recover from access violations, its generally a bad idea to  
> allow for bugs to be turned into features.
>
> Jeremie

Isn't this reason alone strong enough to encourage use of non-null  
references?
And to implement them, since we don't the feature currently.
September 28, 2009
Re: Null references redux
Lionello Lunesu wrote:

> On 27-9-2009 9:20, Walter Bright wrote:
>> language_fan wrote:
>>> The idea behind non-nullable types and other contracts is to catch
>>> these errors on compile time. Sure, the code is a bit harder to write,
>>> but it is safe and never segfaults. The idea is to minimize the amount
>>> of runtime errors of all sorts. That's also how other features of
>>> statically typed languages work.
>>
>>
>> I certainly agree that catching errors at compile time is preferable by
>> far. Where I disagree is the notion that non-nullable types achieve
>> this. I've argued extensively here that they hide errors, not fix them.
>>
>> Also, by "safe" I presume you mean "memory safe" which means free of
>> memory corruption. Null pointer exceptions are memory safe. A null
>> pointer could be caused by memory corruption, but it cannot *cause*
>> memory corruption.
> 
> // t.d
> void main()
> {
>     int* a;
>     a[20000] = 2;
> }
> 
> [C:\Users\Lionello] dmd -run t.d
> 
> [C:\Users\Lionello]
> 
> This code passes on Vista. Granted, needs a big enough offset and some
> luck, but indexing null will never be secure in the current flat memory
> models.
> 
> L.

That is a strong argument. If an object is big enough, modifying it via a 
null reference may still cause memory corruption. Initializing references to 
null does not guarantee memory safety.
September 28, 2009
Re: Null references redux
Nick Sabalausky wrote:
> "Jeremie Pelletier" <jeremiep@gmail.com> wrote in message 
> news:h9mmre$1i8j$1@digitalmars.com...
>> Ary Borenszweig wrote:
>>> Object is not-nullable, Object? (or whatever syntax you like) is 
>>> nullable. So that line is a compile-time error: you can't cast a null to 
>>> an Object (because Object *can't* be null).
>>>
>> union A {
>> Object foo;
>> Object? bar;
>> }
>>
>> Give me a type system, and I will find backdoors :)
>>
> 
> Unions are nothing more than an alternate syntax for a reinterpret cast. And 
> it's an arguably worse syntax because unlike casts, uses of it are 
> indistinguishable from normal safe code, there's nothing to grep for. As 
> such, unions should never be considered any more safe than cast(x)y. The 
> following is just as dangerous as your example above and doesn't even touch 
> the issue of nullability/non-nulability:
> 
> union A {
> int foo;
> float bar;
> }
> 

Yet it's the only way I know of to do bitwise logic on floating points 
in D to extract the exponent, sign and mantissa for example.

And yes they are much, much more than a simple reinterpret cast, a 
simple set of casts will not set the size of the union to its largest 
member. Unions make for elegant types which can have many valid 
representations:

union Vec3F {
	struct { float x, y, z; }
	float[3] v;
}

I just can't picture D without unions :)
September 28, 2009
Re: Null references redux
Max Samukha wrote:
> Lionello Lunesu wrote:
> 
>> On 27-9-2009 9:20, Walter Bright wrote:
>>> language_fan wrote:
>>>> The idea behind non-nullable types and other contracts is to catch
>>>> these errors on compile time. Sure, the code is a bit harder to write,
>>>> but it is safe and never segfaults. The idea is to minimize the amount
>>>> of runtime errors of all sorts. That's also how other features of
>>>> statically typed languages work.
>>>
>>> I certainly agree that catching errors at compile time is preferable by
>>> far. Where I disagree is the notion that non-nullable types achieve
>>> this. I've argued extensively here that they hide errors, not fix them.
>>>
>>> Also, by "safe" I presume you mean "memory safe" which means free of
>>> memory corruption. Null pointer exceptions are memory safe. A null
>>> pointer could be caused by memory corruption, but it cannot *cause*
>>> memory corruption.
>> // t.d
>> void main()
>> {
>>     int* a;
>>     a[20000] = 2;
>> }
>>
>> [C:\Users\Lionello] dmd -run t.d
>>
>> [C:\Users\Lionello]
>>
>> This code passes on Vista. Granted, needs a big enough offset and some
>> luck, but indexing null will never be secure in the current flat memory
>> models.
>>
>> L.
> 
> That is a strong argument. If an object is big enough, modifying it via a 
> null reference may still cause memory corruption. Initializing references to 
> null does not guarantee memory safety.

How is that corruption? These pointers were purposely set to 0x00000002, 
corruption I believe is when memory is modified without the programmer 
being aware of it. For example if the GC was to free memory that is 
still reachable, that would cause corruption.

Corruption is near impossible to trace back, this case is trivial.
September 28, 2009
Re: Null references redux
Jeremie Pelletier wrote:

> Nick Sabalausky wrote:
>> union A {
>> int foo;
>> float bar;
>> }
>> 
> 
> Yet it's the only way I know of to do bitwise logic on floating points
> in D to extract the exponent, sign and mantissa for example.

You could add built-in methods for those operations to the float type:

float bar;

boolean s = bar.sign;
...

Union is very flexible, but unfortunately it's also one of the features that 
can break the type safety in D.
September 28, 2009
Re: Null references redux
Jari-Matti Mäkelä wrote:
> Jeremie Pelletier wrote:
> 
>> Nick Sabalausky wrote:
>>> union A {
>>> int foo;
>>> float bar;
>>> }
>>>
>> Yet it's the only way I know of to do bitwise logic on floating points
>> in D to extract the exponent, sign and mantissa for example.
> 
> You could add built-in methods for those operations to the float type:
> 
> float bar;
> 
> boolean s = bar.sign;
> ...

That would be so inefficient in some cases, you don't always want to 
shift the data like bar.sign implies.

> Union is very flexible, but unfortunately it's also one of the features that 
> can break the type safety in D.

That's the best thing about systems languages: to have a core set of 
rules, and to be able to purposely break them. Even better, you still 
pass go and still get $200.

I don't want a language that takes me by the hand for a walk in the 
park. I want a language that keeps me on my toes and punch me in the 
face every now and then :)
September 28, 2009
Re: Null references redux
Jeremie Pelletier wrote:

> Jari-Matti Mäkelä wrote:
>> Jeremie Pelletier wrote:
>> 
>>> Nick Sabalausky wrote:
>>>> union A {
>>>> int foo;
>>>> float bar;
>>>> }
>>>>
>>> Yet it's the only way I know of to do bitwise logic on floating points
>>> in D to extract the exponent, sign and mantissa for example.
>> 
>> You could add built-in methods for those operations to the float type:
>> 
>> float bar;
>> 
>> boolean s = bar.sign;
>> ...
> 
> That would be so inefficient in some cases, you don't always want to
> shift the data like bar.sign implies.

It depends on the boolean representation. I see no reason why a built-in 
feature should be slower than some bitwise logic operation in user code. 
After all, the set of operations the language provides for the user is a 
subset of all possible operations the language implementation can do.
13 14 15 16 17 18 19 20 21
Top | Discussion index | About this forum | D home