Re: dereferencing null

2012-03-09 Thread Timon Gehr

On 03/09/2012 01:43 AM, bearophile wrote:

Adam D. Ruppe:


D rox the web (and has for a while).


(Oh, you are starting to copy Andrei talk style now :-) The birth of community 
words, idioms and sub-languages is a very common thing, sociology studies such 
things a lot).

But there's always some space for improvements :-)

In D.learn there is a thread titled 0  negative loop condition bug or 
misunderstanding on my part:

http://forum.dlang.org/thread/tbsvfbotcupussmet...@forum.dlang.org

Web coders are not going to appreciate such traps. I think integral bound tests 
at run-time are able to catch part of those problems.

Bye,
bearophile


Comparing signed/unsigned is perfectly reasonable. This is what causes 
the problem discussed in D.learn:


assert(-10U); // fail.


Re: dereferencing null

2012-03-09 Thread bearophile

Timon Gehr:


Comparing signed/unsigned is perfectly reasonable.


Right, but only if the numbers don't get implicit 
reinterpretations to other intervals, as C/C++/D do.


Bye,
bearophile


Re: dereferencing null

2012-03-08 Thread Don Clugston

On 06/03/12 17:05, Sean Kelly wrote:

On Mar 6, 2012, at 3:14 AM, Don Clugstond...@nospam.com  wrote:


Responding to traps is one of the very few examples I know of, where Windows 
got it completely right,
and *nix got it absolutely completely wrong. Most notably, the hardware is 
*designed* for floating point traps to be fully recoverable. It makes perfect 
sense to catch them and continue.
But unfortunately the *nix operating systems are completely broken in this 
regard and there's nothing we can do to fix them.


Does SEH allow recovery at the point of error like signals do?


Yes, it does. It really acts like an interrupt. You can, for example, 
modify registers or memory locations, then perform the equivalent of an 
asm { iret; }, so that you continue at the next instruction. Or, you can 
pass control to any function, after unwinding the stack by any number of 
frames you chose. And, you regain control if any other exception occurs 
during the unwinding, and you're given the chance to change strategy at 
that point.


An SEH handler behaves a bit like setjmp(), it's not a callback.
Most importantly, in comparison to Posix, there are NO LIMITATIONS about 
what you can do in an SEH exception handler. You can call any function 
you like.


The documentation is terrible, but it's really a beautiful design.

 Sometimes I think it would be enough if the Posix spec were worded in 
a way that allowed exceptions to be thrown from signal handlers.


I think that would be difficult to allow. Some of the restrictions seem 
to be quite fundamental. (Otherwise, I'm sure they would have got rid of 
them by now!)


Re: dereferencing null

2012-03-08 Thread Steven Schveighoffer

On Thu, 08 Mar 2012 03:58:22 -0500, Don Clugston d...@nospam.com wrote:


On 06/03/12 17:05, Sean Kelly wrote:

On Mar 6, 2012, at 3:14 AM, Don Clugstond...@nospam.com  wrote:


Responding to traps is one of the very few examples I know of, where  
Windows got it completely right,
and *nix got it absolutely completely wrong. Most notably, the  
hardware is *designed* for floating point traps to be fully  
recoverable. It makes perfect sense to catch them and continue.
But unfortunately the *nix operating systems are completely broken in  
this regard and there's nothing we can do to fix them.


Does SEH allow recovery at the point of error like signals do?


Yes, it does. It really acts like an interrupt. You can, for example,  
modify registers or memory locations, then perform the equivalent of an  
asm { iret; }, so that you continue at the next instruction. Or, you can  
pass control to any function, after unwinding the stack by any number of  
frames you chose. And, you regain control if any other exception occurs  
during the unwinding, and you're given the chance to change strategy at  
that point.


An SEH handler behaves a bit like setjmp(), it's not a callback.
Most importantly, in comparison to Posix, there are NO LIMITATIONS about  
what you can do in an SEH exception handler. You can call any function  
you like.


The documentation is terrible, but it's really a beautiful design.

  Sometimes I think it would be enough if the Posix spec were worded in  
a way that allowed exceptions to be thrown from signal handlers.


I think that would be difficult to allow. Some of the restrictions seem  
to be quite fundamental. (Otherwise, I'm sure they would have got rid of  
them by now!)


IIRC, SEH is patented...

-Steve


Re: dereferencing null

2012-03-08 Thread Andrej Mitrovic
I think what Chad is looking for is a BlackHole/WhiteHole equivalent
which doesn't need abstract functions but which figures out all the
methods of a class at compile time and creates a subclass that
throws/does nothing on method invocation. An 'alias this' field would
be used that is default-initialized with this sentry object. I don't
know why we don't have __traits(allFunction). We have
'getVirtualFunctions' but it requires a function name, but using
allMembers to filter out function names is damn difficult if you ask
me. I've never had an easy time interacting with __traits.


Re: dereferencing null

2012-03-08 Thread H. S. Teoh
On Thu, Mar 08, 2012 at 02:57:00PM +0100, Andrej Mitrovic wrote:
[...]
 I don't know why we don't have __traits(allFunction). We have
 'getVirtualFunctions' but it requires a function name, but using
 allMembers to filter out function names is damn difficult if you ask
 me.

foreach (name; __traits(allMembers, typeof(obj))) {
static if (__traits(compiles, __traits(getMember, obj,
name)))
{
alias typeof(__traits(getMember, obj, name))
type;
static if (is(type==function)) {
// name refers to a function of type
// 'type' here
}
}
}

 I've never had an easy time interacting with __traits.

Me too. I'm guessing that __traits is the way it is due to ease of
implementation in the compiler. It's certainly not very friendly to use.


T

-- 
Маленькие детки - маленькие бедки.


Re: dereferencing null

2012-03-08 Thread Sean Kelly
On Mar 8, 2012, at 12:58 AM, Don Clugston d...@nospam.com wrote:

 On 06/03/12 17:05, Sean Kelly wrote:
 On Mar 6, 2012, at 3:14 AM, Don Clugstond...@nospam.com  wrote:
 
 Responding to traps is one of the very few examples I know of, where 
 Windows got it completely right,
 and *nix got it absolutely completely wrong. Most notably, the hardware is 
 *designed* for floating point traps to be fully recoverable. It makes 
 perfect sense to catch them and continue.
 But unfortunately the *nix operating systems are completely broken in this 
 regard and there's nothing we can do to fix them.
 
 Does SEH allow recovery at the point of error like signals do?
 
 Yes, it does. It really acts like an interrupt. You can, for example, modify 
 registers or memory locations, then perform the equivalent of an asm { iret; 
 }, so that you continue at the next instruction. Or, you can pass control to 
 any function, after unwinding the stack by any number of frames you chose. 
 And, you regain control if any other exception occurs during the unwinding, 
 and you're given the chance to change strategy at that point.
 
 An SEH handler behaves a bit like setjmp(), it's not a callback.
 Most importantly, in comparison to Posix, there are NO LIMITATIONS about what 
 you can do in an SEH exception handler. You can call any function you like.

Wow, sounds like paradise compared to signals. 


 The documentation is terrible, but it's really a beautiful design.
 
 Sometimes I think it would be enough if the Posix spec were worded in a way 
 that allowed exceptions to be thrown from signal handlers.
 
 I think that would be difficult to allow. Some of the restrictions seem to be 
 quite fundamental. (Otherwise, I'm sure they would have got rid of them by 
 now!)

I'm sure it's too late now. And I imagine there was a good reason for it that 
I'm not aware of, just like the restrictions on kernel calls (which could have 
blocked signals during execution). Performance was probably part of it. Ah 
well. The last signal issue I ran into was a deadlock caused by a logger 
routine calling ctime_r inside a sigchild handler.  What a pain. 

Re: dereferencing null - what about something like an check-scope?

2012-03-08 Thread dennis luehring
could it be a good idea to add something like an check-scope for 
modules,functions,etc. for typical fails to easy the detection?


wild-idea-and-syntax-list:
@CheckForNull
@CheckForNaN
@CheckForUnnormalFloat
...

 x.d

modul x

@CheckForNull // will introduce NullChecks for the complete module

..
..
..

-

int test()
{
@CheckForNull; // introduces Null-Checks on the function scope
@CheckForNaN; // introduces NaN-Checks on the function scope
   ...very long evil function...
}

total waste of compiler-developer time - or something to make D better 
in the end?








Re: dereferencing null

2012-03-08 Thread Andrej Mitrovic
On 3/8/12, H. S. Teoh hst...@quickfur.ath.cx wrote:
   foreach (name; __traits(allMembers, typeof(obj))) {
   static if (__traits(compiles, __traits(getMember, obj,
   name)))
   {
   alias typeof(__traits(getMember, obj, name))
   type;
   static if (is(type==function)) {
   // name refers to a function of type
   // 'type' here
   }
   }
   }

 I've never had an easy time interacting with __traits.

Yesterday I've tried the same thing but it didn't work because I was
missing the __traits call. With that in place, here's a very
hardcoded example of what you can do in D:

http://paste.pocoo.org/show/562933/

So now you can catch the exception if the object was uninitialized.
And you didn't have to modify the target class at all.


Re: dereferencing null

2012-03-08 Thread Andrej Mitrovic
Sorry,
mixin(getOverloads!(UnreliableResource)()); should be:
mixin(getOverloads!(Base)());


Re: dereferencing null

2012-03-08 Thread Andrej Mitrovic
Plus I left over some code. Anyway the point is that was just a
hardcoded example of something that's doable, you'd probably want it
to be much more sophisticated before it goes into a library.


Re: dereferencing null - what about something like an check-scope?

2012-03-08 Thread David Eagen
I like the way Scala handles this with the Option class. None 
indicates no value which is equivalent to your null sentinal 
value but it is a value itself so it is always safe to use.


Combined with pattern matching and the orElse methods makes it 
very easy to use one variable that both stores the value and at 
the same time indicates whether it is valid or not. It's not two 
variables that could get out of sync.


Re: dereferencing null

2012-03-08 Thread H. S. Teoh
On Thu, Mar 08, 2012 at 05:49:20PM +0100, Andrej Mitrovic wrote:
 On 3/8/12, H. S. Teoh hst...@quickfur.ath.cx wrote:
  foreach (name; __traits(allMembers, typeof(obj))) {
  static if (__traits(compiles, __traits(getMember, obj,
  name)))
  {
  alias typeof(__traits(getMember, obj, name))
  type;
  static if (is(type==function)) {
  // name refers to a function of type
  // 'type' here
  }
  }
  }
 
  I've never had an easy time interacting with __traits.
 
 Yesterday I've tried the same thing but it didn't work because I was
 missing the __traits call. With that in place, here's a very
 hardcoded example of what you can do in D:
 
 http://paste.pocoo.org/show/562933/
 
 So now you can catch the exception if the object was uninitialized.
 And you didn't have to modify the target class at all.

Cool! That's a really neat way of doing it. Love the combination of
alias this, compile-time introspection, and the awesomeness of D
templates. D r0x0rs!


T

-- 
Your inconsistency is the only consistent thing about you! -- KD


Re: dereferencing null

2012-03-08 Thread Walter Bright

On 3/8/2012 12:58 AM, Don Clugston wrote:

The documentation is terrible, but it's really a beautiful design.


I agree, it really is very flexible and useful. The downside is that it leaves 
significant overhead in functions that are exception-aware, even if they never 
throw or unwind.


And you're right about the documentation. It's incredibly obtuse, probably the 
worst I've ever seen.


Re: dereferencing null

2012-03-08 Thread David Nadlinger

On Thursday, 8 March 2012 at 22:20:10 UTC, Walter Bright wrote:
I agree, it really is very flexible and useful. The downside is 
that it leaves significant overhead in functions that are 
exception-aware, even if they never throw or unwind.


This problem is avoided by the switch to the table-based 
implementation on x86_64, though, while the flexibility, as far 
as I know, still remains.


And you're right about the documentation. It's incredibly 
obtuse, probably the worst I've ever seen.


Yes – I love how everybody (including me) working on SEH code 
seems to end up reverse-engineering at least certain parts of it 
on their own.


David


Re: dereferencing null

2012-03-08 Thread bearophile
Regarding people that desire a compiler switch to add run-time tests inside the 
binary that guard against null seg-faults to turn turn them into errors with a 
stack trace: I have recently shown the D language to a friend. She answered me 
that most code she writes is for the Web and it's not CPU-bound.

So maybe for her D language is not needed, other more flexible languages are 
better for her. On the other hand if you already know D and you already use D 
for other CPU-intensive purposes you may want to use it for situations where a 
very high performance is not necessary at all.

In such situations you don't compile in release-mode (leaving array bound tests 
on), and maybe you want null deference exceptions too, and other things (and 
tolerating some more bloat of the  binary). Things like integral overflow 
errors and null errors allow you to use D in other niches of the programming 
landscape, while they do not hurt high performance D code at all because you 
are able to refuse those things with a compiler switch (the disadvantage is a 
little more complex compiler, but I think in this case this is acceptable).

Generally not giving such choice to the programmers restricts the applicability 
and ecological niche of the D language, giving back no gain.

Bye,
bearophile


Re: dereferencing null

2012-03-08 Thread Adam D. Ruppe

On Friday, 9 March 2012 at 00:19:38 UTC, bearophile wrote:
So maybe for her D language is not needed, other more flexible 
languages are better for her.


D rox the web (and has for a while).


Re: dereferencing null

2012-03-08 Thread bearophile
Adam D. Ruppe:

 D rox the web (and has for a while).

(Oh, you are starting to copy Andrei talk style now :-) The birth of community 
words, idioms and sub-languages is a very common thing, sociology studies such 
things a lot).

But there's always some space for improvements :-)

In D.learn there is a thread titled 0  negative loop condition bug or 
misunderstanding on my part:

http://forum.dlang.org/thread/tbsvfbotcupussmet...@forum.dlang.org

Web coders are not going to appreciate such traps. I think integral bound tests 
at run-time are able to catch part of those problems.

Bye,
bearophile


Re: dereferencing null

2012-03-08 Thread Chad J

On 03/08/2012 10:40 AM, H. S. Teoh wrote:

On Thu, Mar 08, 2012 at 02:57:00PM +0100, Andrej Mitrovic wrote:


I think what Chad is looking for is a BlackHole/WhiteHole equivalent
which doesn't need abstract functions but which figures out all the
methods of a class at compile time and creates a subclass that
throws/does nothing on method invocation. An 'alias this' field would
be used that is default-initialized with this sentry object. I don't
know why we don't have __traits(allFunction). We have
'getVirtualFunctions' but it requires a function name, but using
allMembers to filter out function names is damn difficult if you ask
me. I've never had an easy time interacting with __traits.


Yep.  That would be cool.  Although there should be ways of doing the 
same thing for arrays and possibly even structs.  For structs I wouldn't 
mind adding a boolean field to keep track of its empty-or-not status.




foreach (name; __traits(allMembers, typeof(obj))) {
static if (__traits(compiles,__traits(getMember, obj,
name)))
{
alias typeof(__traits(getMember, obj, name))
type;
static if (is(type==function)) {
// name refers to a function of type
// 'type' here
}
}
}


I've never had an easy time interacting with __traits.


Me too. I'm guessing that __traits is the way it is due to ease of
implementation in the compiler. It's certainly not very friendly to use.


T



Tried this, but it wasn't picking everything up.

I also suspect that inheriting the class being wrapped and picking on 
its methods is going to be a losing battle in the long run for this 
thing.  It doesn't allow the sentry to throw on field access.  It also 
wouldn't work for final classes.  I wonder if opDispatch would do better.


Another mess I was running into was forwarding templated methods.  I 
wonder if this is even possible.  I wish __traits had some way of 
picking up on previous template instantiations (with cycles forbidden, 
of course).  If __traits were beefed up enough, maybe it would be better 
than opDispatch after all.  Hmmm.


I did try this as a struct with an private T t; alias t this; in it. 
It looks like this:


---

import std.c.stdlib;
import std.stdio;

struct Emptiable(T)
{
private static Emptiable!T m_sentinel;
// private NotNull!T t; // TODO
private T t;

alias t this;

public static @property Emptiable!T sentinel()
{
return m_sentinel;
}

static this()
{
void* sentinelMem = malloc(T.sizeof);
m_sentinel = cast(T)sentinelMem;
}

this(A...)(A args)
{
t = new T(args);
}

@property bool isEmpty() const
{
if ( this is m_sentinel )
return true;
else
return false;
}
}

static auto makeEmpty(T)(ref T v)
{
v = T.sentinel;
return v;
}

class Bar
{
int i;

this(int j) { i = j; }

void blah()
{
writefln(blah!);
}

/+void letsTemplate(T)(T f)
{
writefln(%s,f);
}+/
}

void main()
{
auto bar = Emptiable!(Bar).sentinel;
auto foo = new Emptiable!Bar(5);

if ( bar.isEmpty )
writefln(bar is empty, as it should be.);

if ( !foo.isEmpty )
writefln(foo is full, as it should be.);

//foo.letsTemplate(Just a string.);

writefln(foo.i is %s,foo.i);
foo.i = 2;
writefln(foo.i is %s,foo.i);

/+
makeEmpty(foo);
if ( foo.isEmpty )
writefln(foo is now empty.);
writefln(foo.i is %s,foo.i);
+/
}

---

Prints:
bar is empty, as it should be.
foo is full, as it should be.
foo.i is 5
foo.i is 2

---

It's super incomplete.  I am starting to realize that this sort of thing 
leads to a huge amount of weird corner cases.


Also note what happens when it tries to use makeEmpty: it fails because 
auto foo = new Emptiable!Bar(5); allocates an instance of the 
Emptiable struct on the heap, which then allocates a separate instance 
of Bar.  Yuck.  It's that old struct-vs-class construction schism again.




Re: dereferencing null

2012-03-07 Thread Timon Gehr

On 03/07/2012 02:40 AM, Chad J wrote:

On 03/06/2012 12:19 PM, Timon Gehr wrote:

...

For example:
http://pm.inf.ethz.ch/publications/getpdf.php/bibname/Own/id/SummersMuellerTR11.pdf



CTFE and static constructors solve that issue for static data.


I can't seem to download the PDF... it always gives me just two bytes.



Same here. Strange. Interestingly, it works if you copy and paste the 
link into google.


Re: dereferencing null

2012-03-07 Thread Timon Gehr

On 03/07/2012 02:40 AM, Chad J wrote:

But to initialize non-null fields, I suspect we would need to be able to
do stuff like this:

class Foo
{
int dummy;
}

class Bar
{
Foo foo = new Foo();

this() { foo.dummy = 5; }
}

Which would be lowered by the compiler into this:

class Bar
{
// Assume we've already checked for bogus assignments.
// It is now safe to make this nullable.
Nullable!(Foo) foo;

this()
{
// Member initialization is done first.
foo = new Foo();

// Then programmer-supplied ctor code runs after.
foo.dummy = 5;
}
}

I remember C# being able to do this. I never understood why D doesn't
allow this. Without it, I have to repeat myself a lot, and that is just
wrong ;).]


It is not sufficient.

class Bar{
Foo foo = new Foo(this);
void method(){...}
}
class Foo{
this(Bar bar){bar.foo.method();}
}


Re: dereferencing null

2012-03-07 Thread Steven Schveighoffer
On Mon, 05 Mar 2012 22:51:28 -0500, Jonathan M Davis jmdavisp...@gmx.com  
wrote:



On Monday, March 05, 2012 21:04:20 Steven Schveighoffer wrote:

On Mon, 05 Mar 2012 20:17:32 -0500, Michel Fortin

michel.for...@michelf.com wrote:
 That said, throwing an exception might not be a better response all  
the

 time. On my operating system (Mac OS X) when a program crashes I get a
 nice crash log with the date, a stack trace for each thread with named
 functions, the list of all loaded libraries, and the list of VM  
regions

 dumped into ~/Library/Logs/CrashReporter/. That's very useful when you
 have a customer experiencing a crash with your software, as you can  
ask

 for the crash log. Can't you do the same on other operating systems?

It depends on the OS facilities and the installed libraries for such
features.  It's eminently possible, and I think on Windows, you can  
catch

such exceptions too in external programs to do the same sort of dumping.
On Linux, you get a Segmentation Fault message (or nothing if you have
no terminal showing the output), and the program goes away.  That's the
default behavior.  I think it's better in any case to do *something*  
other
than just print Segmentation Fault by default.  If someone has a way  
to
hook this in a better fashion, we can include that, but I hazard to  
guess

it will not be on stock Linux boxes.


All you have to do is add a signal handler which handles SIGSEV and have  
it
print out a stacktrace. It's pretty easy to do. It _is_ the sort of  
thing that
programs may want to override (to handle other signals), so I'm not  
quite sure
what the best way to handle that is without causing problems for them  
(e.g.
initialization order could affect which handler is added last and is  
therefore
the one used). Maybe a function should be added to druntime which wraps  
the
glibc function so that programs can add their signal handler through  
_it_, and

if that happens, the default one won't be used.


Install the default (stack-trace printing) handler before calling any of  
the static constructors.  Any call to signal after that will override the  
installed handler.


-Steve


Re: dereferencing null

2012-03-07 Thread Steven Schveighoffer
On Tue, 06 Mar 2012 23:07:24 -0500, Walter Bright  
newshou...@digitalmars.com wrote:



On 3/6/2012 8:05 PM, Walter Bright wrote:

What I'm talking about is the idea that one can recover from seg faults
resulting from program bugs.


I've written about this before, but I want to emphasize that attempting  
to recover from program BUGS is the absolutely WRONG way to go about  
writing fail-safe, critical, fault-tolerant software.


100% agree.  I just want as much information about the bug as possible  
before the program exits.


-Steve


Re: dereferencing null

2012-03-07 Thread Steven Schveighoffer
On Mon, 05 Mar 2012 23:58:48 -0500, Chad J  
chadjoan@__spam.is.bad__gmail.com wrote:



On 03/05/2012 11:27 PM, Jonathan M Davis wrote:

On Tuesday, March 06, 2012 05:11:30 Martin Nowak wrote:

There are two independent discussions being conflated here. One about
getting more
information out of crashes even in release mode and the other about
adding runtime checks to prevent crashing merely in debug builds.


A segfault should _always_ terminate a program - as should  
dereferencing a
null pointer. Those are fatal errors. If we had extra checks, they  
would have

to result in NullPointerErrors, not NullPointerExceptions. It's horribly
broken to try and recover from dereferencing a null pointer. So, the  
question
then becomes whether adding the checks and getting an Error thrown is  
worth
doing as opposed to simply detecting it and printing out a stack trace.  
And
throwing an Error is arguably _worse_, because it means that you can't  
get a

useful core dump.

Really, I think that checking for null when dereferencing is out of the
question. What we need is to detect it and print out a stacktrace. That  
will

maximize the debug information without costing performance.

- Jonathan M Davis


Why is it fatal?


A segmentation fault indicates that a program tried to access memory that  
is not available.  Since the 0 page is never allocated, any null pointer  
dereferencing results in a seg fault.


However, there are several causes of seg faults:

1. You forgot to initialize a variable.
2. Your memory has been corrupted, and some corrupted pointer now points  
into no-mem land.

3. You are accessing memory that has been deallocated.

Only 1 is benign.  2 and 3 are fatal.  Since you cannot know which of  
these three happened, the only valid choice is to terminate.


I think the correct option is to print a stack trace, and abort the  
program.


I'd like to be able to catch these.  I tend to run into a lot of fairly  
benign sources of these, and they should be try-caught so that the user  
doesn't get the boot unnecessarily.  Unnecessary crashing can lose user  
data.  Maybe a warning message is sufficient: hey that last thing you  
did didn't turn out so well; please don't do that again. followed by  
some automatic emailing of admins.  And the email would contain a nice  
stack trace with line numbers and stack values and... I can dream huh.


You cannot be sure if your program is in a sane state.

I might be convinced that things like segfaults in the /general case/  
are fatal.  It could be writing to memory outside the bounds of an array  
which is both not bounds-checked and may or may not live on the stack.  
Yuck, huh.  But this is not the same as a null-dereference:


Foo f = null;
f.bar = 4;  // This is exception worthy, yes,
 // but how does it affect unrelated parts of the program?


Again, this is a simple case.  There is also this case:

Foo f = new Foo();
... // some code that corrupts f so that it is now null
f.bar = 4;

This is not a continue execution case, and cannot be distinguished from  
the simple case by compiler or library code.


Philosophically, any null pointer access is a program error, not a user  
error, and should not be considered for normal execution.  Terminating  
execution is the only right choice.


-Steve


Re: dereferencing null

2012-03-07 Thread Steven Schveighoffer
On Wed, 07 Mar 2012 09:22:27 -0500, Chad J  
chadjoan@__spam.is.bad__gmail.com wrote:



On 03/07/2012 07:57 AM, Steven Schveighoffer wrote:

On Mon, 05 Mar 2012 23:58:48 -0500, Chad J
chadjoan@__spam.is.bad__gmail.com wrote:



Why is it fatal?


A segmentation fault indicates that a program tried to access memory
that is not available. Since the 0 page is never allocated, any null
pointer dereferencing results in a seg fault.

However, there are several causes of seg faults:

1. You forgot to initialize a variable.
2. Your memory has been corrupted, and some corrupted pointer now points
into no-mem land.
3. You are accessing memory that has been deallocated.

Only 1 is benign. 2 and 3 are fatal. Since you cannot know which of
these three happened, the only valid choice is to terminate.

I think the correct option is to print a stack trace, and abort the
program.



Alright, I think I see where the misunderstanding is coming from.

I have only ever encountered (1).  And I've encountered it a lot.


(1) occurs a lot, and in most cases, happens reliably.  Most QA cycles  
should find them.  There should be no case in which this is not a program  
error, to be fixed.
(2) and (3) are sinister because errors that occur are generally far away  
from the root cause, and the memory you are using is compromised.  For  
example, a memory corruption can cause an error several hours later when  
you try to use the corrupted memory.


If allowed to continue, such corrupt memory programs can cause lots of  
problems, e.g. corrupt your saved data, or run malicious code (buffer  
overflow attack).  It's not worth saving anything.


I didn't even consider (2) and (3) as possibilities.  Those are far from  
my mind.


I still have a nagging doubt though: since the dereference in question  
is null, then there is no way for that particular dereference to corrupt  
other memory.  The only way this happens in (2) and (3) is that related  
code tries to write to invalid memory.  But if we have other measures in  
place to prevent that (bounds checking, other hardware signals, etc),  
then how is it still possible to corrupt memory?


The null dereference may be a *result* of memory corruption.

example:

class Foo {void foo(){}}

void main()
{
   int[2] x = [1, 2];
   Foo f = new Foo;

   x.ptr[2] = 0; // oops killed f
   f.foo(); // segfault
}

Again, this one is benign, but it doesn't have to be.  I could have just  
nullified my return stack pointer, etc. along with f.


The larger point is, a SEGV means memory is not as it is expected.  Once  
you don't trust your memory, you might as well stop.


-Steve


Re: dereferencing null

2012-03-07 Thread Chad J

On Wednesday, 7 March 2012 at 14:23:18 UTC, Chad J wrote:

On 03/07/2012 07:57 AM, Steven Schveighoffer wrote:

On Mon, 05 Mar 2012 23:58:48 -0500, Chad J
chadjoan@__spam.is.bad__gmail.com wrote:



Why is it fatal?


A segmentation fault indicates that a program tried to access 
memory
that is not available. Since the 0 page is never allocated, 
any null

pointer dereferencing results in a seg fault.

However, there are several causes of seg faults:

1. You forgot to initialize a variable.
2. Your memory has been corrupted, and some corrupted pointer 
now points

into no-mem land.
3. You are accessing memory that has been deallocated.

Only 1 is benign. 2 and 3 are fatal. Since you cannot know 
which of

these three happened, the only valid choice is to terminate.

I think the correct option is to print a stack trace, and 
abort the

program.



Alright, I think I see where the misunderstanding is coming 
from.


I have only ever encountered (1).  And I've encountered it a 
lot.


I didn't even consider (2) and (3) as possibilities.  Those are 
far from my mind.


I still have a nagging doubt though: since the dereference in 
question is null, then there is no way for that particular 
dereference to corrupt other memory.  The only way this happens 
in (2) and (3) is that related code tries to write to invalid 
memory.  But if we have other measures in place to prevent that 
(bounds checking, other hardware signals, etc), then how is it 
still possible to corrupt memory?




[...]

-Steve


I spoke too soon!
We missed one:

1. You forgot to initialize a variable.
2. Your memory has been corrupted, and some corrupted pointer
 now points into no-mem land.
3. You are accessing memory that has been deallocated.
4. null was being used as a sentinal value, and it snuck into
 a place where the value should not be a sentinal anymore.

I will now change what I said to reflect this:

I think I see where the misunderstanding is coming from.

I encounter (1) from time to time.  It isn't a huge problem 
because usually if I declare something the next thing on my mind 
is initializing it.  Even if I forget, I'll catch it in early 
testing.  It tends to never make it to anyone else's desk, unless 
it's a regression.  Regressions like this aren't terribly common 
though.  If you make my program crash from (1), I'll live.


I didn't even consider (2) and (3) as possibilities.  Those are 
far from my mind.  I think I'm used to VM languages at this point 
(C#, Java, Actionscript 3, Haxe, Synergy/DE|DBL, etc).  In the 
VM, (2) and (3) can't happen.  I never worry about those.  Feel 
free to crash these in D.


I encounter (4) a lot.  I really don't want my programs crashed 
when (4) happens.  Such crashes would be super annoying, and they 
can happen at very bad times.


--

Now then, I have 2 things to say about this:

- Why can't we distinguish between these?  As I said in my 
previous thoughts, we should have ways of ruling out (2) and (3), 
thus ensuring that our NullDerefException was caused by only (1) 
or (4).  It's possible in VM languages, but given that the VM is 
merely a cheesey abstraction, I beleive that it's always possible 
to accomplish the same things in D %100 of the time.  Usually 
this requires isolating the system bits from the abstractions.  
Saying it can't be done would be giving up way too easily, and 
you can miss the hidden treasure that way.


- If I'm given some sensible way of handling sentinal values then 
(4) will become a non-issue.  Then that leaves (1-3), and I am OK 
if those cause mandatory crashing.  I know I'm probably opening 
an old can of worms, but D is quite powerful and I think we 
should be able to solve this stuff.  My instincts tell me that 
managing sentinal values with special patterns in memory (ex: 
null values or separate boolean flags) all have pitfalls 
(null-derefs or SSOT violations that lead to desync).  Perhaps 
D's uber-powerful type system can rescue us?


The only other problem with this is... what if our list is not 
exhaustive, and (5) exists?





Re: dereferencing null

2012-03-07 Thread Chad J

On Wednesday, 7 March 2012 at 14:23:18 UTC, Chad J wrote:

On 03/07/2012 07:57 AM, Steven Schveighoffer wrote:

On Mon, 05 Mar 2012 23:58:48 -0500, Chad J
chadjoan@__spam.is.bad__gmail.com wrote:



Why is it fatal?


A segmentation fault indicates that a program tried to access 
memory
that is not available. Since the 0 page is never allocated, 
any null

pointer dereferencing results in a seg fault.

However, there are several causes of seg faults:

1. You forgot to initialize a variable.
2. Your memory has been corrupted, and some corrupted pointer 
now points

into no-mem land.
3. You are accessing memory that has been deallocated.

Only 1 is benign. 2 and 3 are fatal. Since you cannot know 
which of

these three happened, the only valid choice is to terminate.

I think the correct option is to print a stack trace, and 
abort the

program.



Alright, I think I see where the misunderstanding is coming 
from.


I have only ever encountered (1).  And I've encountered it a 
lot.


I didn't even consider (2) and (3) as possibilities.  Those are 
far from my mind.


I still have a nagging doubt though: since the dereference in 
question is null, then there is no way for that particular 
dereference to corrupt other memory.  The only way this happens 
in (2) and (3) is that related code tries to write to invalid 
memory.  But if we have other measures in place to prevent that 
(bounds checking, other hardware signals, etc), then how is it 
still possible to corrupt memory?




[...]

-Steve


I spoke too soon!
We missed one:

1. You forgot to initialize a variable.
2. Your memory has been corrupted, and some corrupted pointer
   now points into no-mem land.
3. You are accessing memory that has been deallocated.
4. null was being used as a sentinal value, and it snuck into
   a place where the value should not be a sentinal anymore.

I will now change what I said to reflect this:

I think I see where the misunderstanding is coming from.

I encounter (1) from time to time.  It isn't a huge problem
because usually if I declare something the next thing on my mind
is initializing it.  Even if I forget, I'll catch it in early
testing.  It tends to never make it to anyone else's desk, unless
it's a regression.  Regressions like this aren't terribly common
though.  If you make my program crash from (1), I'll live.

I didn't even consider (2) and (3) as possibilities.  Those are
far from my mind.  I think I'm used to VM languages at this point
(C#, Java, Actionscript 3, Haxe, Synergy/DE|DBL, etc).  In the
VM, (2) and (3) can't happen.  I never worry about those.  Feel
free to crash these in D.

I encounter (4) a lot.  I really don't want my programs crashed
when (4) happens.  Such crashes would be super annoying, and they
can happen at very bad times.

--

Now then, I have 2 things to say about this:

- Why can't we distinguish between these?  As I said in my
previous thoughts, we should have ways of ruling out (2) and (3),
thus ensuring that our NullDerefException was caused by only (1)
or (4).  It's possible in VM languages, but given that the VM is
merely a cheesey abstraction, I beleive that it's always possible
to accomplish the same things in D %100 of the time.  Usually
this requires isolating the system bits from the abstractions.
Saying it can't be done would be giving up way too easily, and
you can miss the hidden treasure that way.

- If I'm given some sensible way of handling sentinal values then
(4) will become a non-issue.  Then that leaves (1-3), and I am OK
if those cause mandatory crashing.  I know I'm probably opening
an old can of worms, but D is quite powerful and I think we
should be able to solve this stuff.  My instincts tell me that
managing sentinal values with special patterns in memory (ex:
null values or separate boolean flags) all have pitfalls
(null-derefs or SSOT violations that lead to desync).  Perhaps
D's uber-powerful type system can rescue us?

The only other problem with this is... what if our list is not
exhaustive, and (5) exists?




Re: dereferencing null

2012-03-07 Thread Steven Schveighoffer
On Wed, 07 Mar 2012 10:10:32 -0500, Chad J  
chadjoan@__spam.is.bad__gmail.com wrote:



On Wednesday, 7 March 2012 at 14:23:18 UTC, Chad J wrote:

On 03/07/2012 07:57 AM, Steven Schveighoffer wrote:

On Mon, 05 Mar 2012 23:58:48 -0500, Chad J
chadjoan@__spam.is.bad__gmail.com wrote:



Why is it fatal?


A segmentation fault indicates that a program tried to access memory
that is not available. Since the 0 page is never allocated, any null
pointer dereferencing results in a seg fault.

However, there are several causes of seg faults:

1. You forgot to initialize a variable.
2. Your memory has been corrupted, and some corrupted pointer now  
points

into no-mem land.
3. You are accessing memory that has been deallocated.

Only 1 is benign. 2 and 3 are fatal. Since you cannot know which of
these three happened, the only valid choice is to terminate.

I think the correct option is to print a stack trace, and abort the
program.



Alright, I think I see where the misunderstanding is coming from.

I have only ever encountered (1).  And I've encountered it a lot.

I didn't even consider (2) and (3) as possibilities.  Those are far  
from my mind.


I still have a nagging doubt though: since the dereference in question  
is null, then there is no way for that particular dereference to  
corrupt other memory.  The only way this happens in (2) and (3) is that  
related code tries to write to invalid memory.  But if we have other  
measures in place to prevent that (bounds checking, other hardware  
signals, etc), then how is it still possible to corrupt memory?




[...]

-Steve


I spoke too soon!
We missed one:

1. You forgot to initialize a variable.
2. Your memory has been corrupted, and some corrupted pointer
  now points into no-mem land.
3. You are accessing memory that has been deallocated.
4. null was being used as a sentinal value, and it snuck into
  a place where the value should not be a sentinal anymore.

I will now change what I said to reflect this:

I think I see where the misunderstanding is coming from.

I encounter (1) from time to time.  It isn't a huge problem because  
usually if I declare something the next thing on my mind is initializing  
it.  Even if I forget, I'll catch it in early testing.  It tends to  
never make it to anyone else's desk, unless it's a regression.   
Regressions like this aren't terribly common though.  If you make my  
program crash from (1), I'll live.


I didn't even consider (2) and (3) as possibilities.  Those are far from  
my mind.  I think I'm used to VM languages at this point (C#, Java,  
Actionscript 3, Haxe, Synergy/DE|DBL, etc).  In the VM, (2) and (3)  
can't happen.  I never worry about those.  Feel free to crash these in D.


I encounter (4) a lot.  I really don't want my programs crashed when (4)  
happens.  Such crashes would be super annoying, and they can happen at  
very bad times.


You can use sentinels other than null.

-Steve


Re: dereferencing null

2012-03-07 Thread H. S. Teoh
On Wed, Mar 07, 2012 at 09:22:27AM -0500, Chad J wrote:
 On 03/07/2012 07:57 AM, Steven Schveighoffer wrote:
[...]
 However, there are several causes of seg faults:
 
 1. You forgot to initialize a variable.
 2. Your memory has been corrupted, and some corrupted pointer now
 points into no-mem land.
 3. You are accessing memory that has been deallocated.
 
 Only 1 is benign. 2 and 3 are fatal. Since you cannot know which of
 these three happened, the only valid choice is to terminate.
 
 I think the correct option is to print a stack trace, and abort the
 program.
 
 
 Alright, I think I see where the misunderstanding is coming from.
 
 I have only ever encountered (1).  And I've encountered it a lot.
 
 I didn't even consider (2) and (3) as possibilities.  Those are far
 from my mind.
 
 I still have a nagging doubt though: since the dereference in
 question is null, then there is no way for that particular
 dereference to corrupt other memory.  The only way this happens in
 (2) and (3) is that related code tries to write to invalid memory.
 But if we have other measures in place to prevent that (bounds
 checking, other hardware signals, etc), then how is it still
 possible to corrupt memory?
[...]

It's not that the null pointer itself corrupts memory. It's that the
null pointer is a sign that something may have corrupted memory *before*
you got to that point.

The point is, it's impossible to tell whether the null pointer was
merely the result of forgetting to initialize something, or it's a
symptom of a far more sinister problem. The source of the problem could
potentially be very far away, in unrelated code, and only when you tried
to access the pointer, you discover that something is wrong.

At that point, it may very well be the case that the null pointer isn't
just a benign uninitialized pointer, but the result of a memory
corruption, perhaps an exploit in the process of taking over your
application, or some internal consistency error that is in the process
of destroying user data. Trying to continue is a bad idea, since you'd
be letting the exploit take over, or allowing user data to get even more
corrupted than it already is.


T

-- 
Be in denial for long enough, and one day you'll deny yourself of things you 
wish you hadn't.


Re: dereferencing null

2012-03-07 Thread Jonathan M Davis
On Wednesday, March 07, 2012 07:55:35 H. S. Teoh wrote:
 It's not that the null pointer itself corrupts memory. It's that the
 null pointer is a sign that something may have corrupted memory *before*
 you got to that point.
 
 The point is, it's impossible to tell whether the null pointer was
 merely the result of forgetting to initialize something, or it's a
 symptom of a far more sinister problem. The source of the problem could
 potentially be very far away, in unrelated code, and only when you tried
 to access the pointer, you discover that something is wrong.
 
 At that point, it may very well be the case that the null pointer isn't
 just a benign uninitialized pointer, but the result of a memory
 corruption, perhaps an exploit in the process of taking over your
 application, or some internal consistency error that is in the process
 of destroying user data. Trying to continue is a bad idea, since you'd
 be letting the exploit take over, or allowing user data to get even more
 corrupted than it already is.

Also, while D does much more to protect you from stuff like memory corruption 
than C/C++ does, it's still a systems language. Stuff like that can definitely 
happen. If you're writing primarily in SafeD, then it's very much minimized, 
but it's not necessarily eliminated. All it takes is a bug in @system code 
which could corrupt memory, and voila, you have corrupted memory, and an @safe 
function could get a segfault even though it's correct code. It's likely to be 
a very rare occurrence, but it's possible. A since when you get a segfault, 
you can't know what caused it, you have to assume that it could have been 
caused by one of the nastier possibilites rather than a relatively benign one.

And since ultimately, your program should be checking for null before 
derefencing a variable in any case where it could be null, segfaulting due to 
dereferencing a null pointer is a program bug which should be caught in 
testing - like assertions in general are - rather than having the program 
attempt to recover from it. And if you do _that_, the odds of a segfault being 
due to something very nasty just go up, making it that much more of a bad idea 
to try and recover from one.

- Jonathan M Davis


Re: dereferencing null

2012-03-07 Thread Chad J

On 03/07/2012 04:41 AM, Timon Gehr wrote:

On 03/07/2012 02:40 AM, Chad J wrote:

But to initialize non-null fields, I suspect we would need to be able to
do stuff like this:

class Foo
{
int dummy;
}

class Bar
{
Foo foo = new Foo();

this() { foo.dummy = 5; }
}

Which would be lowered by the compiler into this:

class Bar
{
// Assume we've already checked for bogus assignments.
// It is now safe to make this nullable.
Nullable!(Foo) foo;

this()
{
// Member initialization is done first.
foo = new Foo();

// Then programmer-supplied ctor code runs after.
foo.dummy = 5;
}
}

I remember C# being able to do this. I never understood why D doesn't
allow this. Without it, I have to repeat myself a lot, and that is just
wrong ;).]


It is not sufficient.

class Bar{
Foo foo = new Foo(this);
void method(){...}
}
class Foo{
this(Bar bar){bar.foo.method();}
}


Lowered it a bit to try to compile, because it seems Foo doesn't have a 
method() :


import std.stdio;

class Bar{
  Foo foo;
  this()
  {
foo = new Foo(this);
  }
  void method(){ writefln(poo); }
}
class Foo{
  this(Bar bar){bar.foo.method();}
}

void main()
{
}

And, it doesn't:
main.d(12): Error: no property 'method' for type 'main.Foo'

Though, more to the point:
I would probably forbid Foo foo = new Foo(this);.  The design that 
leads to this is creating circular dependencies, which is usually bad to 
begin with.  Would we lose much of value?


Re: dereferencing null

2012-03-07 Thread Timon Gehr

On 03/08/2012 01:24 AM, Chad J wrote:

On 03/07/2012 04:41 AM, Timon Gehr wrote:

On 03/07/2012 02:40 AM, Chad J wrote:

But to initialize non-null fields, I suspect we would need to be able to
do stuff like this:

class Foo
{
int dummy;
}

class Bar
{
Foo foo = new Foo();

this() { foo.dummy = 5; }
}

Which would be lowered by the compiler into this:

class Bar
{
// Assume we've already checked for bogus assignments.
// It is now safe to make this nullable.
Nullable!(Foo) foo;

this()
{
// Member initialization is done first.
foo = new Foo();

// Then programmer-supplied ctor code runs after.
foo.dummy = 5;
}
}

I remember C# being able to do this. I never understood why D doesn't
allow this. Without it, I have to repeat myself a lot, and that is just
wrong ;).]


It is not sufficient.

class Bar{
Foo foo = new Foo(this);
void method(){...}
}
class Foo{
this(Bar bar){bar.foo.method();}
}


Lowered it a bit to try to compile, because it seems Foo doesn't have a
method() :

import std.stdio;

class Bar{
Foo foo;
this()
{
foo = new Foo(this);
}
void method(){ writefln(poo); }
}
class Foo{
this(Bar bar){bar.foo.method();}
}

void main()
{
}

And, it doesn't:
main.d(12): Error: no property 'method' for type 'main.Foo'



Just move the method from Bar to Foo.

import std.stdio;

class Bar{
Foo foo;
this()
{
foo = new Foo(this);
}
}
class Foo{
this(Bar bar){bar.foo.method();}
void method(){ writefln(poo); }
}

void main()
{
auto bar = new Bar;
}




Though, more to the point:
I would probably forbid Foo foo = new Foo(this);. The design that
leads to this is creating circular dependencies, which is usually bad to
begin with.


Circular object references are often justified.


Would we lose much of value?


Well this would amount to forbidding escaping an object from its 
constructor, as well as forbidding calling any member functions from the 
constructor. Also, if you *need* to create a circular structure, you'd 
have to use sentinel objects. Those are worse than null.




Re: dereferencing null

2012-03-07 Thread Chad J

On 03/07/2012 10:21 AM, Steven Schveighoffer wrote:

On Wed, 07 Mar 2012 10:10:32 -0500, Chad J
chadjoan@__spam.is.bad__gmail.com wrote:


On Wednesday, 7 March 2012 at 14:23:18 UTC, Chad J wrote:

I spoke too soon!
We missed one:

1. You forgot to initialize a variable.
2. Your memory has been corrupted, and some corrupted pointer
now points into no-mem land.
3. You are accessing memory that has been deallocated.
4. null was being used as a sentinal value, and it snuck into
a place where the value should not be a sentinal anymore.

I will now change what I said to reflect this:

I think I see where the misunderstanding is coming from.

I encounter (1) from time to time. It isn't a huge problem because
usually if I declare something the next thing on my mind is
initializing it. Even if I forget, I'll catch it in early testing. It
tends to never make it to anyone else's desk, unless it's a
regression. Regressions like this aren't terribly common though. If
you make my program crash from (1), I'll live.

I didn't even consider (2) and (3) as possibilities. Those are far
from my mind. I think I'm used to VM languages at this point (C#,
Java, Actionscript 3, Haxe, Synergy/DE|DBL, etc). In the VM, (2) and
(3) can't happen. I never worry about those. Feel free to crash these
in D.

I encounter (4) a lot. I really don't want my programs crashed when
(4) happens. Such crashes would be super annoying, and they can happen
at very bad times.


You can use sentinels other than null.

-Steve


Example?

Here, if you want, I'll start with a typical case.  Please make it right.

class UnreliableResource
{
this(string sourceFile) {...}
this(uint userId) {...}
void doTheThing() {...}
}

void main()
{
// Set this to a sentinal value for cases where the source does
//   not exist, thus preventing proper initialization of res.
UnreliableResource res = null;

// The point here is that obtaining this unreliable resource
//   is tricky business, and therefore complicated.
//
if ( std.file.exists(some_special_file) )
{
res = new UnreliableResource(some_special_file);
}
else
{
uint uid = getUserIdSomehow();
if ( isValidUserId(uid) )
{
res = new UnreliableResource(uid);
}
}

// Do some other stuff.
...

// Now use the resource.
try
{
thisCouldBreakButItWont(res);
}
// Fairly safe if we were in a reasonable VM.
catch ( NullDerefException e )
{
writefln(This shouldn't happen, but it did.);
}
}

void thisCouldBreakButItWont(UnreliableResource res)
{
if ( res != null )
{
res.doTheThing();
}
else
{
doSomethingUsefulThatCanHappenWhenResIsNotAvailable();
writefln(Couldn't find the resource thingy.);
writefln(Resetting the m-rotor.  (NOO!));
}
}

Please follow these constraints:

- Do not use a separate boolean variable for determining whether or not 
'res' could be created.  This violates a kind of SSOT 
(http://en.wikipedia.org/wiki/Single_Source_of_Truth) because it allows 
cases where the hypothetical resIsInitialized variable is true but res 
isn't actually initialized, or where resIsInitialized is false but res 
is actually initialized.  It also doesn't throw catchable exceptions 
when the uninitialized class has methods called on it.  In my pansy 
VM-based languages I always prefer to risk the null sentinal.


- Do not modify the implementation of UnreliableResource.  It's not 
always possible.


- Try to make the solution something that could, in principle, be placed 
into Phobos and reused without a lot of refactoring in the original code.


...

Now I will think about this a bit...

This reminds me a lot of algebraic data types.  I kind of want to say 
something like:

auto res = empty | UnreliableResource;

and then unwrap it:

...
thisCantBreakAnymore(res);
}

void thisCantBreakAnymore(UnreliableResource res)
{
res.doTheThing();
}

void thisCantBreakAnymore(empty)
{
doSomethingUsefulThatCanHappenWhenResIsNotAvailable();
writefln(Couldn't find the resource thingy.);
writefln(Resetting the m-rotor.  (NOO!));
}


I'm not absolutely sure I'd want to go that path though, and since D is 
unlikely to do any of those things, I just want to be able to catch an 
exception if the sentinel value tries to have the doTheThing() method 
called on it.


I can maybe see invariants being used for this:

class UnreliableResource
{
bool initialized = false;

invariant
{
if (!initialized)
throw new Exception(Not initialized.);
}

void initialize(string sourceFile)
  

Re: dereferencing null

2012-03-07 Thread Chad J

On 03/07/2012 02:09 PM, Jonathan M Davis wrote:

On Wednesday, March 07, 2012 07:55:35 H. S. Teoh wrote:

It's not that the null pointer itself corrupts memory. It's that the
null pointer is a sign that something may have corrupted memory *before*
you got to that point.

The point is, it's impossible to tell whether the null pointer was
merely the result of forgetting to initialize something, or it's a
symptom of a far more sinister problem. The source of the problem could
potentially be very far away, in unrelated code, and only when you tried
to access the pointer, you discover that something is wrong.

At that point, it may very well be the case that the null pointer isn't
just a benign uninitialized pointer, but the result of a memory
corruption, perhaps an exploit in the process of taking over your
application, or some internal consistency error that is in the process
of destroying user data. Trying to continue is a bad idea, since you'd
be letting the exploit take over, or allowing user data to get even more
corrupted than it already is.


Also, while D does much more to protect you from stuff like memory corruption
than C/C++ does, it's still a systems language. Stuff like that can definitely
happen. If you're writing primarily in SafeD, then it's very much minimized,
but it's not necessarily eliminated. All it takes is a bug in @system code
which could corrupt memory, and voila, you have corrupted memory, and an @safe
function could get a segfault even though it's correct code. It's likely to be
a very rare occurrence, but it's possible. A since when you get a segfault,
you can't know what caused it, you have to assume that it could have been
caused by one of the nastier possibilites rather than a relatively benign one.

And since ultimately, your program should be checking for null before
derefencing a variable in any case where it could be null, segfaulting due to
dereferencing a null pointer is a program bug which should be caught in
testing - like assertions in general are - rather than having the program
attempt to recover from it. And if you do _that_, the odds of a segfault being
due to something very nasty just go up, making it that much more of a bad idea
to try and recover from one.

- Jonathan M Davis


I can see where you're coming from now.

As I mentioned in another post, my lack of consideration for this 
indicator of memory corruption is probably a reflection of my bias 
towards VM'd languages.


I still don't buy the whole it's a program bug that should be caught in 
testing.  I mean... true, but sometimes it isn't.  Especially since 
testing and assertions can never be %100 thorough.  What then?  Sorry, 
enjoy your suffering?


At that point I would like to have a better way to do sentinel values. 
I'd at least like to get an exception of some kind if I try to access a 
value that /shouldn't/ be there (as opposed to something that /should/ 
be there but /isn't/).


Combine that with sandboxing and I might just be satisfied for the time 
being.


See my reply to Steve for more details.  It's the one that starts like this:


Example?

Here, if you want, I'll start with a typical case.  Please make it right.

class UnreliableResource
{
this(string sourceFile) {...}
this(uint userId) {...}
void doTheThing() {...}
}


Re: dereferencing null

2012-03-07 Thread Chad J

On 03/07/2012 07:39 PM, Timon Gehr wrote:

On 03/08/2012 01:24 AM, Chad J wrote:


Though, more to the point:
I would probably forbid Foo foo = new Foo(this);. The design that
leads to this is creating circular dependencies, which is usually bad to
begin with.


Circular object references are often justified.


Would we lose much of value?


Well this would amount to forbidding escaping an object from its
constructor, as well as forbidding calling any member functions from the
constructor. Also, if you *need* to create a circular structure, you'd
have to use sentinel objects. Those are worse than null.



OK, that does sound unusually harsh.


Re: dereferencing null

2012-03-07 Thread Jonathan M Davis
On Wednesday, March 07, 2012 20:44:59 Chad J wrote:
 On 03/07/2012 10:21 AM, Steven Schveighoffer wrote:
  You can use sentinels other than null.
  
  -Steve
 
 Example?

Create an instance of the class which is immutable and represents an invalid 
value. You could check whether something is that value with the is operator, 
since there's only one of it. You could even make it a derived class and have 
all of its functions throw a particular exception if someone tries to call 
them.

- Jonathan M Davis


Re: dereferencing null

2012-03-07 Thread Chad J

On 03/07/2012 10:08 PM, Jonathan M Davis wrote:

On Wednesday, March 07, 2012 20:44:59 Chad J wrote:

On 03/07/2012 10:21 AM, Steven Schveighoffer wrote:

You can use sentinels other than null.

-Steve


Example?


Create an instance of the class which is immutable and represents an invalid
value. You could check whether something is that value with the is operator,
since there's only one of it. You could even make it a derived class and have
all of its functions throw a particular exception if someone tries to call
them.

- Jonathan M Davis


Makes sense.  Awfully labor-intensive though.  Doesn't work well on 
classes that can't be easily altered.  That is, it violates this:

- Do not modify the implementation of UnreliableResource.  It's not always 
possible.


But, maybe it can be turned it into a template and made to work for 
arrays too...


Re: dereferencing null

2012-03-07 Thread Jonathan M Davis
On Wednesday, March 07, 2012 22:36:50 Chad J wrote:
 On 03/07/2012 10:08 PM, Jonathan M Davis wrote:
  On Wednesday, March 07, 2012 20:44:59 Chad J wrote:
  On 03/07/2012 10:21 AM, Steven Schveighoffer wrote:
  You can use sentinels other than null.
  
  -Steve
  
  Example?
  
  Create an instance of the class which is immutable and represents an
  invalid value. You could check whether something is that value with the
  is operator, since there's only one of it. You could even make it a
  derived class and have all of its functions throw a particular exception
  if someone tries to call them.
  
  - Jonathan M Davis
 
 Makes sense.  Awfully labor-intensive though.  Doesn't work well on
 
 classes that can't be easily altered.  That is, it violates this:
  - Do not modify the implementation of UnreliableResource.  It's not always
  possible.
 But, maybe it can be turned it into a template and made to work for
 arrays too...

Personally, I'd probably just use null. But if you want a sentinel other than 
null, it's quite feasible.

- Jonathan M Davis


Re: dereferencing null

2012-03-07 Thread Chad J

On 03/07/2012 10:40 PM, Jonathan M Davis wrote:

On Wednesday, March 07, 2012 22:36:50 Chad J wrote:

On 03/07/2012 10:08 PM, Jonathan M Davis wrote:

On Wednesday, March 07, 2012 20:44:59 Chad J wrote:

On 03/07/2012 10:21 AM, Steven Schveighoffer wrote:

You can use sentinels other than null.

-Steve


Example?


Create an instance of the class which is immutable and represents an
invalid value. You could check whether something is that value with the
is operator, since there's only one of it. You could even make it a
derived class and have all of its functions throw a particular exception
if someone tries to call them.

- Jonathan M Davis


Makes sense.  Awfully labor-intensive though.  Doesn't work well on

classes that can't be easily altered.  That is, it violates this:

- Do not modify the implementation of UnreliableResource.  It's not always
possible.

But, maybe it can be turned it into a template and made to work for
arrays too...


Personally, I'd probably just use null. But if you want a sentinel other than
null, it's quite feasible.

- Jonathan M Davis


Wait, so you'd use null and then have the program unconditionally crash 
whenever you (inevitably) mess up sentinel logic?


Re: dereferencing null

2012-03-07 Thread Jonathan M Davis
On Wednesday, March 07, 2012 22:58:44 Chad J wrote:
 On 03/07/2012 10:40 PM, Jonathan M Davis wrote:
  On Wednesday, March 07, 2012 22:36:50 Chad J wrote:
  On 03/07/2012 10:08 PM, Jonathan M Davis wrote:
  On Wednesday, March 07, 2012 20:44:59 Chad J wrote:
  On 03/07/2012 10:21 AM, Steven Schveighoffer wrote:
  You can use sentinels other than null.
  
  -Steve
  
  Example?
  
  Create an instance of the class which is immutable and represents an
  invalid value. You could check whether something is that value with the
  is operator, since there's only one of it. You could even make it a
  derived class and have all of its functions throw a particular exception
  if someone tries to call them.
  
  - Jonathan M Davis
  
  Makes sense.  Awfully labor-intensive though.  Doesn't work well on
  
  classes that can't be easily altered.  That is, it violates this:
  - Do not modify the implementation of UnreliableResource.  It's not
  always
  possible.
  
  But, maybe it can be turned it into a template and made to work for
  arrays too...
  
  Personally, I'd probably just use null. But if you want a sentinel other
  than null, it's quite feasible.
  
  - Jonathan M Davis
 
 Wait, so you'd use null and then have the program unconditionally crash
 whenever you (inevitably) mess up sentinel logic?

Yes. Proper testing will find most such problems. And it's not like having a 
non-null sentinel is going to prevent you from having problems. It just means 
that you're not distinguishing between a variable that you forgot to 
initialize and one which you set to the sentinel value. Your program can die 
from a variable being null in either case. And in _both_ cases, it's generally 
unsafe to continue executing your program anyway.

And honestly, in my experience, null pointers are a very rare thing. You catch 
them through solid testing.

- Jonathan M Davis


Re: dereferencing null

2012-03-07 Thread Chad J

On 03/07/2012 11:17 PM, Jonathan M Davis wrote:

On Wednesday, March 07, 2012 22:58:44 Chad J wrote:

On 03/07/2012 10:40 PM, Jonathan M Davis wrote:

On Wednesday, March 07, 2012 22:36:50 Chad J wrote:

On 03/07/2012 10:08 PM, Jonathan M Davis wrote:

On Wednesday, March 07, 2012 20:44:59 Chad J wrote:

On 03/07/2012 10:21 AM, Steven Schveighoffer wrote:

You can use sentinels other than null.

-Steve


Example?


Create an instance of the class which is immutable and represents an
invalid value. You could check whether something is that value with the
is operator, since there's only one of it. You could even make it a
derived class and have all of its functions throw a particular exception
if someone tries to call them.

- Jonathan M Davis


Makes sense.  Awfully labor-intensive though.  Doesn't work well on

classes that can't be easily altered.  That is, it violates this:

- Do not modify the implementation of UnreliableResource.  It's not
always
possible.


But, maybe it can be turned it into a template and made to work for
arrays too...


Personally, I'd probably just use null. But if you want a sentinel other
than null, it's quite feasible.

- Jonathan M Davis


Wait, so you'd use null and then have the program unconditionally crash
whenever you (inevitably) mess up sentinel logic?


Yes. Proper testing will find most such problems. And it's not like having a
non-null sentinel is going to prevent you from having problems. It just means
that you're not distinguishing between a variable that you forgot to
initialize and one which you set to the sentinel value. Your program can die
from a variable being null in either case. And in _both_ cases, it's generally
unsafe to continue executing your program anyway.



The important difference in using explicit sentinel values here is that 
they are not null, and thus very unlikely to have been caused by memory 
corruption.  It allows us to distinguish between the two sources of 
empty variables.


With a better way to do sentinel values, I can isolate my cleaner 
looking code from the scarier looking code that comes from any number of 
places.


I also am not too worried about null values that come from stuff that 
was simply forgotten, instead of intentionally nulled.  I DO tend to 
catch those really early in testing, and they are unlikely to happen to 
begin with due to the close association between declaration and 
initialization.



And honestly, in my experience, null pointers are a very rare thing. You catch
them through solid testing.

- Jonathan M Davis



Sorry, your testing doesn't help me as well as you probably wish it 
does.  Our experiences must be very different.  I run into a lot of 
cases where things can't be tested automatically, or at least not 
easily.  Think along the lines of graphics operations, interactively 
driven code (ex: event lifetimes), network code, etc.  Testing can help 
things between endpoints, but it doesn't help much where the rubber 
meets the road.


And that's just game dev.  Then I go to work at my job, the one that 
makes money, and experience code from the 80s.  Rewriting it is 
completely impractical for near-term projects (though a complete 
phase-out of crufty old crap is on the horizon one way or another!). 
Yes it has bugs.  If I had an attitude of crash on every little nit 
then these things wouldn't last a few seconds (OK, exaggeration).  So I 
recover as well as possible, and occasionally rewrite strategically 
important pieces.  But the world is NOT perfect, so relying on it being 
perfect is %100 unhelpful to me.  Also, quit your job is not an 
acceptable solution. ;)  Now, in principle, we will never have to deal 
with D code like that.  Nonetheless, these experiences do make me 
severely afraid of lacking the tools that keep me safe.


And then there are still those occasional weird problems where sentinel 
values are needed, and its so stateful that there's a vanishingly 
close-to-zero chance that testing will catch the stuff that it needs to.
So I test it as well as I can and leave a if all else fails, DO THIS 
next to the dubious code.  Indiscriminate segfaulting deprives me of 
this last-ditch option.  There is no longer even a way to crash 
elegantly.  It all just goes to hell.


Long story short: in practice, I find that recovering from sentinel 
dereference is not only VERY safe, but also orders of magnitude less 
frustrating for both my users and me.


(Memory corruption, on the other hand, is something I am very unfamiliar 
with, and sort of afraid of.  So I'm willing to ditch nulls.)


Re: dereferencing null

2012-03-06 Thread Walter Bright

On 3/5/2012 11:51 AM, Jacob Carlborg wrote:

Yeah, C and C++ might not do what's suggested but basically all other languages
do it.



People turn to C and C++ for systems work and high performance.


Re: dereferencing null

2012-03-06 Thread James Miller
If you have a possible null, then check for it *yourself* sometimes
you know its null, sometimes you don't have any control. However, the
compiler has no way of knowing that. Its basically an all-or-nothing
thing with the compiler.

However, the compiler can (and I think does) warn of possible
null-related errors. It doesn't fail, because, again, it can't be
certain of what is an error and what is not. And it can't know, since
that is the Halting Problem.

I'm not sure what the fuss is here, we cannot demand that every little
convenience be packed into D, at some point we need to face facts that
we are still programming, and sometimes things go wrong. The best
arguments I've seen so far is to install a handler that catches the
SEGFAULT in linux, and does whatever SEH stuff it does in windows and
print a stacktrace. If this happens in a long-running process, then,
to be blunt, tough. Unless you're telling me that the only way to
reproduce the bug is to run the program for the same amount of time in
near-identical conditions, then sir, you fail at being a detective.

If you have a specific need for extreme safety and no sharp corners,
use Java, or some other VM language, PHP comes to mind as well. If you
want a systems programming language that is geared for performance,
with modern convenience then stick around, do I have the language for
you! Stop thinking in hypotheticals, because no language can cover
every situation; What if this is running in a space ship for 12 years
and the segfault is caused by space bees?! is not something we should
be thinking about. If a process fails, then it fails, you try to
figure out what happened (you do have logging on this mysterious
program right? then fix it.

Its not easy, but if it was easy, we'd be out of jobs.

/rant

--
James Miller


Re: dereferencing null

2012-03-06 Thread Walter Bright

On 3/5/2012 12:05 PM, Nick Sabalausky wrote:

Walter Brightnewshou...@digitalmars.com  wrote in message
news:jiunst$qrm$1...@digitalmars.com...


3. Intercepting and recovering from seg faults, div by 0, etc., all sounds
great on paper. In practice, it is almost always wrong. The only exception
(!) to the rule is when sandboxing a plugin (as you suggested).



The purpose of catching exceptions is to respond to a condition. Recovery is
merely *one* such type of response.



Right, but Sandeep and I were specifically talking about recovering.


Re: dereferencing null

2012-03-06 Thread Timon Gehr

On 03/05/2012 05:39 AM, Adam D. Ruppe wrote:

On Monday, 5 March 2012 at 03:24:32 UTC, Chad J wrote:

News to me. I've had bad runs with that back in the day, but maybe
things have improved a bit.


Strangely, I've never had a problem with gdb and D,
as far back as 2007.
(at least for the basic stack trace kind of stuff).

But, yeah, they've been improving a lot of things
recently too.


Non-nullable types would be really cool right about now.


Huh, I thought there was one in phobos by now.

You could spin your own with something like this:

struct NotNull(T) {
T t;
alias t this;
@disable this();
@disable this(typeof(null));
this(T value) {
assert(value !is null);
t = value;
}

@disable typeof(this) opAssign(typeof(null));
typeof(this) opAssign(T rhs) {
assert(rhs !is null);
t = rhs;
return this;
}
}


This will catch usages of the null literal at
compile time, and other null references at runtime
as soon as you try to use it.

With the disabled default constructor, you are forced
to provide an initializer when you use it, so no
accidental null will slip in.

The alias this means NotNull!T is substitutable for T,
so you can drop it into existing apis.


It's that I simply cannot expect users to run my code in a debugger.


:) I'm lucky if I can get more from my users than
the site doesn't work!


The problem is that they don't help me when I missed a spot and didn't
use assertions, contracts, or invariants.


Aye, I've had it happen. The not null types might help,
though tbh I've never used anything like this in practice
so maybe not. I don't really know.


This is quite close, but real support for non-nullable types means that 
they are the default and checked statically, ideally using data flow 
analysis.






Re: dereferencing null

2012-03-06 Thread Jacob Carlborg

On 2012-03-06 10:11, James Miller wrote:

If you have a possible null, then check for it *yourself* sometimes
you know its null, sometimes you don't have any control. However, the
compiler has no way of knowing that. Its basically an all-or-nothing
thing with the compiler.


If I know there is a possible null, then of course I check for it. But I 
MAY NOT KNOW there is a possible null. People make mistakes, I make 
mistakes. But I guess you just turn of exceptions and another error 
handling completely because you never ever make a mistake.



However, the compiler can (and I think does) warn of possible
null-related errors. It doesn't fail, because, again, it can't be
certain of what is an error and what is not. And it can't know, since
that is the Halting Problem.

I'm not sure what the fuss is here, we cannot demand that every little
convenience be packed into D, at some point we need to face facts that
we are still programming, and sometimes things go wrong. The best
arguments I've seen so far is to install a handler that catches the
SEGFAULT in linux, and does whatever SEH stuff it does in windows and
print a stacktrace. If this happens in a long-running process, then,
to be blunt, tough. Unless you're telling me that the only way to
reproduce the bug is to run the program for the same amount of time in
near-identical conditions, then sir, you fail at being a detective.


On Mac OS X the runtime would only need to catch any exception (as it 
already does) and print the stack trace. But also re-throw the exception 
to let the OS handle the logging of the exception (at least I hope that 
will work).



If you have a specific need for extreme safety and no sharp corners,
use Java, or some other VM language, PHP comes to mind as well. If you
want a systems programming language that is geared for performance,
with modern convenience then stick around, do I have the language for
you! Stop thinking in hypotheticals, because no language can cover
every situation; What if this is running in a space ship for 12 years
and the segfault is caused by space bees?! is not something we should
be thinking about. If a process fails, then it fails, you try to
figure out what happened (you do have logging on this mysterious
program right? then fix it.

Its not easy, but if it was easy, we'd be out of jobs.

/rant

--
James Miller



--
/Jacob Carlborg


Re: dereferencing null

2012-03-06 Thread Don Clugston

On 04/03/12 04:34, Walter Bright wrote:

On 3/3/2012 6:53 PM, Sandeep Datta wrote:

It's been there for 10 years, and turns out to be a solution looking
for a
problem.


I beg to differ, the ability to catch and respond to such asynchronous
exceptions is vital to the stable operation of long running software.

It is not hard to see how this can be useful in programs which depend
on plugins
to extend functionality (e.g. IIS, Visual Studio, OS with drivers as
plugins
etc). A misbehaving plugin has the potential to bring down the whole
house if
hardware exceptions cannot be safely handled within the host
application. Thus
the inability of handling such exceptions undermines D's ability to
support
dynamically loaded modules of any kind and greatly impairs modularity.

Also note hardware exceptions are not limited to segfaults there are
other
exceptions like division by zero, invalid operation, floating point
exceptions
(overflow, underflow) etc.

Plus by using this approach (SEH) you can eliminate the software null
checks and
avoid taking a hit on performance.

So in conclusion I think it will be worth our while to supply
something like a
NullReferenceException (and maybe NullPointerException for raw
pointers) which
will provide more context than a simple segfault (and that too without
a core
dump). Additional information may include things like a stacktrace (like
Vladimir said in another post) with line numbers, file/module names
etc. Please
take a look at C#'s exception hierarchy for some inspiration (not that
you need
any but it's nice to have some consistency across languages too). I am
just a
beginner in D but I hope D has something like exception chaining in C#
using
which we can chain exceptions as we go to capture the chain of events
which led
to failure.


As I said, it already does that (on Windows). There is an access
violation exception. Try it on windows, you'll see it.

1. SEH isn't portable. There's no way to make it work under non-Windows
systems.

2. Converting SEH to D exceptions is not necessary to make a stack trace
dump work.

3. Intercepting and recovering from seg faults, div by 0, etc., all
sounds great on paper. In practice, it is almost always wrong. The only
exception (!) to the rule is when sandboxing a plugin (as you
suggested). Making such a sandbox work is highly system specific, and
doesn't always fit into the D exception model (in fact, it never does
outside of Windows).


Responding to traps is one of the very few examples I know of, where 
Windows got it completely right,
and *nix got it absolutely completely wrong. Most notably, the hardware 
is *designed* for floating point traps to be fully recoverable. It makes 
perfect sense to catch them and continue.
But unfortunately the *nix operating systems are completely broken in 
this regard and there's nothing we can do to fix them.




Re: dereferencing null

2012-03-06 Thread bearophile
James Miller:

 If you have a possible null, then check for it *yourself* sometimes
 you know its null, sometimes you don't have any control. However, the
 compiler has no way of knowing that. Its basically an all-or-nothing
 thing with the compiler.

In a normal program there are many situations where the programmer knows a 
class reference or a pointer can't be null. If the type system of the language 
allows you to write down this semantic information with some kind of 
annotation, and the compiler is able to analyze the code a bit to make that 
correct and handy, some null-related bugs don't happen. And this costs nothing 
at run-time (but maybe it increases the compilation time a bit).


 I'm not sure what the fuss is here, we cannot demand that every little
 convenience be packed into D, at some point we need to face facts that
 we are still programming, and sometimes things go wrong.

I agree. On the other hand null-related bugs are common enough and bad enough 
that improving their management in some way (helping avoid them, helping their 
debug) is more than just a little convenience.


 If you have a specific need for extreme safety and no sharp corners,
 use Java, or some other VM language, PHP comes to mind as well.

PHP is not at the top of the list of the languages for people that want 
extreme safety.

Bye,
bearophile


Re: dereferencing null

2012-03-06 Thread Chad J

On 03/06/2012 02:54 AM, Jacob Carlborg wrote:

On 2012-03-06 08:53, Jacob Carlborg wrote:

On 2012-03-06 03:04, Steven Schveighoffer wrote:

Certainly for Mac OS X, it should do the most informative appropriate
thing for the OS it's running on. Does the above happen for D programs
currently on Mac OS X?


When an exception if thrown and uncaught it will print the stack trace
to in the terminal (if run in the terminal). If the program ends with a
segmentation fault the stack trace will be outputted to a log file.



Outputting to a log file is handle by the OS and not by druntime.



It sounds like what you'd want to do is walk the stack and print a trace 
to stderr without actually jumping execution.  Well, check for being 
caught first.  Once that's printed, then trigger an OS error and quit.


Re: dereferencing null

2012-03-06 Thread Chad J

On 03/06/2012 03:27 AM, Walter Bright wrote:

On 3/5/2012 11:51 AM, Jacob Carlborg wrote:

Yeah, C and C++ might not do what's suggested but basically all other
languages
do it.



People turn to C and C++ for systems work and high performance.


Optional.  Flags.

If there is a truly unavoidable trade-off, then you give users CHOICE. 
Your opinion on this matter does not work well for /everyone/ in practice.


Not to mention that there seems to be a completely avoidable trade-off 
here.  A few posts have mentioned handlers in Linux that would work for 
printing traces, though not for recovery.  Seems kinda no-brainer.


I'd still want the /choice/ to incur higher runtime overhead to make 
null dereferences and maybe a few other obvious ones behave consistently 
with other exceptions in the language.  *I* would set this flag in a 
heartbeat; *you* don't have to.


Re: dereferencing null

2012-03-06 Thread bearophile
Sandeep Datta:

 I am just going to leave this here...
 
 *Fast Bounds Checking Using Debug Register*
 
 http://www.ecsl.cs.sunysb.edu/tr/TR225.pdf

Is this idea usable in DMD to speed up D code compiled in non-release mode?

Bye,
bearophile


Re: dereferencing null

2012-03-06 Thread Michel Fortin

On 2012-03-06 10:53:19 +, Jacob Carlborg d...@me.com said:

On Mac OS X the runtime would only need to catch any exception (as it 
already does) and print the stack trace. But also re-throw the 
exception to let the OS handle the logging of the exception (at least I 
hope that will work).


Actually if you want a useful crash log the exception shouldn't be 
caught at all, because reaching the catch handler requires unwinding 
the stack which will ruin the stack trace for the log file. Printing 
the stack trace should be done in the exception handling code if no 
catch handler can be found, after which it can crash and let the OS do 
its thing. And for that to work there should be no catch block around 
the call to D main in the runtime initialization code.


--
Michel Fortin
michel.for...@michelf.com
http://michelf.com/



Re: dereferencing null

2012-03-06 Thread Jacob Carlborg

On 2012-03-06 13:48, Chad J wrote:

On 03/06/2012 02:54 AM, Jacob Carlborg wrote:

On 2012-03-06 08:53, Jacob Carlborg wrote:

On 2012-03-06 03:04, Steven Schveighoffer wrote:

Certainly for Mac OS X, it should do the most informative appropriate
thing for the OS it's running on. Does the above happen for D programs
currently on Mac OS X?


When an exception if thrown and uncaught it will print the stack trace
to in the terminal (if run in the terminal). If the program ends with a
segmentation fault the stack trace will be outputted to a log file.



Outputting to a log file is handle by the OS and not by druntime.



It sounds like what you'd want to do is walk the stack and print a trace
to stderr without actually jumping execution. Well, check for being
caught first. Once that's printed, then trigger an OS error and quit.


I'm just writing how it works, not what I want to do.

--
/Jacob Carlborg


Re: dereferencing null

2012-03-06 Thread foobar

On Tuesday, 6 March 2012 at 09:11:07 UTC, James Miller wrote:
If you have a possible null, then check for it *yourself* 
sometimes
you know its null, sometimes you don't have any control. 
However, the
compiler has no way of knowing that. Its basically an 
all-or-nothing

thing with the compiler.

However, the compiler can (and I think does) warn of possible
null-related errors. It doesn't fail, because, again, it can't 
be
certain of what is an error and what is not. And it can't know, 
since

that is the Halting Problem.

I'm not sure what the fuss is here, we cannot demand that every 
little
convenience be packed into D, at some point we need to face 
facts that
we are still programming, and sometimes things go wrong. The 
best
arguments I've seen so far is to install a handler that catches 
the
SEGFAULT in linux, and does whatever SEH stuff it does in 
windows and
print a stacktrace. If this happens in a long-running process, 
then,
to be blunt, tough. Unless you're telling me that the only way 
to
reproduce the bug is to run the program for the same amount of 
time in
near-identical conditions, then sir, you fail at being a 
detective.


If you have a specific need for extreme safety and no sharp 
corners,
use Java, or some other VM language, PHP comes to mind as well. 
If you
want a systems programming language that is geared for 
performance,
with modern convenience then stick around, do I have the 
language for
you! Stop thinking in hypotheticals, because no language can 
cover
every situation; What if this is running in a space ship for 
12 years
and the segfault is caused by space bees?! is not something we 
should

be thinking about. If a process fails, then it fails, you try to
figure out what happened (you do have logging on this mysterious
program right? then fix it.

Its not easy, but if it was easy, we'd be out of jobs.

/rant

--
James Miller


The only halting problem I see here is trying to find any logic 
in the above misplaced rant.


The compiler can implement non-nullable types and prevent NPE 
bugs with zero run-time cost by employing the type system. This 
is a simple concept that has nothing to do with VMs and 
implementations for it do exist in other languages.


Even the inventor of the pointer concept himself confesses that 
null-ability was a grave mistake. [I forgot his name but the i'm 
sure Google can find the video]


I really wish that people would stop comparing everything to 
c/c++. Both are ancient pieces of obsolete technology and the 
trade-offs they provide are irrelevant today. This is why we use 
new languages such as D.





Re: dereferencing null

2012-03-06 Thread foobar

On Tuesday, 6 March 2012 at 10:19:19 UTC, Timon Gehr wrote:

This is quite close, but real support for non-nullable types 
means that they are the default and checked statically, ideally 
using data flow analysis.


I agree that non-nullable types should be made the default and 
statically checked but data flow analysis here is redundant.

consider:
T foo = ..; // T is not-nullable
T? bar = ..; // T? is nullable
bar = foo; // legal implicit coercion T - T?
foo = bar; // compile-time type mismatch error
//correct way:
if (bar) { // make sure bar isn't null
  // compiler knows that cast(T)bar is safe
  foo = bar;
}

of course we can employ additional syntax sugar such as:
foo = bar || default_value;

furthermore:
foo.method(); // legal
bar.method(); // compile-time error

it's all easily implementable in the type system.


Re: dereferencing null

2012-03-06 Thread Sean Kelly
On Mar 6, 2012, at 3:14 AM, Don Clugston d...@nospam.com wrote:
 
 Responding to traps is one of the very few examples I know of, where Windows 
 got it completely right,
 and *nix got it absolutely completely wrong. Most notably, the hardware is 
 *designed* for floating point traps to be fully recoverable. It makes perfect 
 sense to catch them and continue.
 But unfortunately the *nix operating systems are completely broken in this 
 regard and there's nothing we can do to fix them.

Does SEH allow recovery at the point of error like signals do?  Sometimes I 
think it would be enough if the Posix spec were worded in a way that allowed 
exceptions to be thrown from signal handlers.

Re: dereferencing null

2012-03-06 Thread Martin Nowak
On Tue, 06 Mar 2012 14:22:09 +0100, bearophile bearophileh...@lycos.com  
wrote:



Sandeep Datta:


I am just going to leave this here...

*Fast Bounds Checking Using Debug Register*

http://www.ecsl.cs.sunysb.edu/tr/TR225.pdf


Is this idea usable in DMD to speed up D code compiled in non-release  
mode?


Bye,
bearophile


Array accesses are already bounds checked in a much more reliable way than
what the paper proposes. Furthermore the solution in the paper needs  
kernel support.




Re: dereferencing null

2012-03-06 Thread Martin Nowak

On Tue, 06 Mar 2012 12:14:56 +0100, Don Clugston d...@nospam.com wrote:


On 04/03/12 04:34, Walter Bright wrote:

On 3/3/2012 6:53 PM, Sandeep Datta wrote:

It's been there for 10 years, and turns out to be a solution looking
for a
problem.


I beg to differ, the ability to catch and respond to such asynchronous
exceptions is vital to the stable operation of long running software.

It is not hard to see how this can be useful in programs which depend
on plugins
to extend functionality (e.g. IIS, Visual Studio, OS with drivers as
plugins
etc). A misbehaving plugin has the potential to bring down the whole
house if
hardware exceptions cannot be safely handled within the host
application. Thus
the inability of handling such exceptions undermines D's ability to
support
dynamically loaded modules of any kind and greatly impairs modularity.

Also note hardware exceptions are not limited to segfaults there are
other
exceptions like division by zero, invalid operation, floating point
exceptions
(overflow, underflow) etc.

Plus by using this approach (SEH) you can eliminate the software null
checks and
avoid taking a hit on performance.

So in conclusion I think it will be worth our while to supply
something like a
NullReferenceException (and maybe NullPointerException for raw
pointers) which
will provide more context than a simple segfault (and that too without
a core
dump). Additional information may include things like a stacktrace  
(like

Vladimir said in another post) with line numbers, file/module names
etc. Please
take a look at C#'s exception hierarchy for some inspiration (not that
you need
any but it's nice to have some consistency across languages too). I am
just a
beginner in D but I hope D has something like exception chaining in C#
using
which we can chain exceptions as we go to capture the chain of events
which led
to failure.


As I said, it already does that (on Windows). There is an access
violation exception. Try it on windows, you'll see it.

1. SEH isn't portable. There's no way to make it work under non-Windows
systems.

2. Converting SEH to D exceptions is not necessary to make a stack trace
dump work.

3. Intercepting and recovering from seg faults, div by 0, etc., all
sounds great on paper. In practice, it is almost always wrong. The only
exception (!) to the rule is when sandboxing a plugin (as you
suggested). Making such a sandbox work is highly system specific, and
doesn't always fit into the D exception model (in fact, it never does
outside of Windows).


Responding to traps is one of the very few examples I know of, where  
Windows got it completely right,
and *nix got it absolutely completely wrong. Most notably, the hardware  
is *designed* for floating point traps to be fully recoverable. It makes  
perfect sense to catch them and continue.
But unfortunately the *nix operating systems are completely broken in  
this regard and there's nothing we can do to fix them.



Yeah, it's true for FPU traps. You need signals+longjmp to handle them.
Though with SEH you shouldn't forget to fninit before continuing or your
FPU stack might overflow.


Re: dereferencing null

2012-03-06 Thread Christopher Bergqvist

On Tuesday, 6 March 2012 at 15:46:54 UTC, foobar wrote:

On Tuesday, 6 March 2012 at 10:19:19 UTC, Timon Gehr wrote:

This is quite close, but real support for non-nullable types 
means that they are the default and checked statically, 
ideally using data flow analysis.


I agree that non-nullable types should be made the default and 
statically checked but data flow analysis here is redundant.

consider:
T foo = ..; // T is not-nullable
T? bar = ..; // T? is nullable
bar = foo; // legal implicit coercion T - T?
foo = bar; // compile-time type mismatch error
//correct way:
if (bar) { // make sure bar isn't null
  // compiler knows that cast(T)bar is safe
  foo = bar;
}

of course we can employ additional syntax sugar such as:
foo = bar || default_value;

furthermore:
foo.method(); // legal
bar.method(); // compile-time error

it's all easily implementable in the type system.


I agree with the above and would also suggest something along the 
lines of:

assert (bar) { // make sure it isn't null in debug builds
   bar.method(); // legal
}

The branchy null-check would then disappear in build 
configurations with asserts disabled.


Re: dereferencing null

2012-03-06 Thread Mantis

06.03.2012 8:04, Chad J пишет:

On 03/06/2012 12:07 AM, Jonathan M Davis wrote:


If you dereference a null pointer, there is a serious bug in your 
program.

Continuing is unwise. And if it actually goes so far as to be a segfault
(since the hardware caught it rather than the program), it is beyond 
a doubt
unsafe to continue. On rare occasion, it might make sense to try and 
recover
from dereferencing a null pointer, but it's like catching an 
AssertError. It's
rarely a good idea. Continuing would mean trying to recover from a 
logic error
in your program. Your program obviously already assumed that the 
variable
wasn't null, or it would have checked for null. So from the point of 
view of

your program's logic, you are by definition in an undefined state, and
continuing will have unexpected and potentially deadly behavior.

- Jonathan M Davis


This could be said for a lot of things: array-out-of-bounds 
exceptions, file-not-found exceptions, conversion exception, etc.  If 
the programmer thought about it, they would have checked the array 
length, checked for file existence before opening it, been more 
careful about converting things, etc.


It's different: with array-out-of-bounds there's no hardware detection, 
so its either checked in software or unchecked (in best case you'll have 
access violation or segfault, but otherwise going past the bounds of 
array leads to undefined behavior). Both file-not-found and conv 
exceptions often rely on user's input, in which case they do not 
necessarily mean bug in a program.


To me, the useful difference between fatal and non-fatal things is how 
well isolated the failure is.  Out of memory errors and writes into 
unexpected parts of memory are very bad things and can corrupt 
completely unrelated sections of code.  The other things I've 
mentioned, null-dereference included, cannot do this.


Null-dereferences and such can be isolated to sections of code.  A 
section of code might become compromised by the dereference, but the 
code outside of that section is still fine and can continue working.


Example:
[...]
And if riskyShenanigans were to modify global state... well, it's no 
longer so well isolated anymore.  This is just a disadvantage of 
global state, and it will be true with many other possible exceptions 
too.


Long story short: I don't see how an unexpected behavior in one part 
of a program will necessarily create unexpected behavior in all parts 
of the program, especially when good encapsulation is practiced.


Thoughts?

If riskyShenanigans nullifies reference in a process, then it must check 
it before dereferencing. There's obviously a bug, and if program will 
leave a proper crash log you shouldn't have problems finding and fixing 
this bug. If you don't have access to function's source, then you cannot 
guarantee it's safeness and isolation, so recovering from exception is 
unsafe.


Re: dereferencing null

2012-03-06 Thread Chad J

On 03/06/2012 03:39 PM, Mantis wrote:

06.03.2012 8:04, Chad J пишет:

On 03/06/2012 12:07 AM, Jonathan M Davis wrote:


If you dereference a null pointer, there is a serious bug in your
program.
Continuing is unwise. And if it actually goes so far as to be a segfault
(since the hardware caught it rather than the program), it is beyond
a doubt
unsafe to continue. On rare occasion, it might make sense to try and
recover
from dereferencing a null pointer, but it's like catching an
AssertError. It's
rarely a good idea. Continuing would mean trying to recover from a
logic error
in your program. Your program obviously already assumed that the
variable
wasn't null, or it would have checked for null. So from the point of
view of
your program's logic, you are by definition in an undefined state, and
continuing will have unexpected and potentially deadly behavior.

- Jonathan M Davis


This could be said for a lot of things: array-out-of-bounds
exceptions, file-not-found exceptions, conversion exception, etc. If
the programmer thought about it, they would have checked the array
length, checked for file existence before opening it, been more
careful about converting things, etc.


It's different: with array-out-of-bounds there's no hardware detection,
so its either checked in software or unchecked (in best case you'll have
access violation or segfault, but otherwise going past the bounds of
array leads to undefined behavior). Both file-not-found and conv
exceptions often rely on user's input, in which case they do not
necessarily mean bug in a program.



Alright.


To me, the useful difference between fatal and non-fatal things is how
well isolated the failure is. Out of memory errors and writes into
unexpected parts of memory are very bad things and can corrupt
completely unrelated sections of code. The other things I've
mentioned, null-dereference included, cannot do this.

Null-dereferences and such can be isolated to sections of code. A
section of code might become compromised by the dereference, but the
code outside of that section is still fine and can continue working.

Example:
[...]
And if riskyShenanigans were to modify global state... well, it's no
longer so well isolated anymore. This is just a disadvantage of global
state, and it will be true with many other possible exceptions too.

Long story short: I don't see how an unexpected behavior in one part
of a program will necessarily create unexpected behavior in all parts
of the program, especially when good encapsulation is practiced.

Thoughts?


If riskyShenanigans nullifies reference in a process, then it must check
it before dereferencing. There's obviously a bug, and if program will
leave a proper crash log you shouldn't have problems finding and fixing
this bug. If you don't have access to function's source, then you cannot
guarantee it's safeness and isolation, so recovering from exception is
unsafe.


But what do you say to the notion of isolation?  someFunc is isolated 
from riskyShenanigans becuase it /knows/ what state is touched by 
riskyShenanigans.  If riskyShenanigans does something strange and 
unexpected, and yes, it does have a bug in it, then I feel that someFunc 
should be able to reset the state touched by riskyShenanigans and 
continue.


The thing I find really strange here is that there's this belief that if 
feature A is buggy then the unrelated feature B shouldn't work either. 
Why?  Shouldn't the user be able to continue using feature B?


Btw, crashing a program is bad.  That can lose data that the user has 
entered but not yet stored.  I should have a very good reason before I 
let this happen.


It would also be extremely frustrating for a user to have a program 
become crippled because some feature they don't even use will 
occasionally dereference null and crash the thing.  Then they have to 
wait for me to fix it, and I'm busy, so it could be awhile.


My impression so far is that this hinges on some kind of where there's 
one, there's more argument.  I am unconvinced because programs tend to 
have bugs anyways.  riskyShenanigans doing a null-dereference once 
doesn't mean it's any more likely to produce corrupt results the rest of 
the time: it can produce corrupt results anyways, because it is a 
computer program written by a fallible human being.  Anyone trying to be 
really careful should validate the results in someFunc.


Re: dereferencing null

2012-03-06 Thread Chad J

On 03/06/2012 12:19 PM, Timon Gehr wrote:

On 03/06/2012 04:46 PM, foobar wrote:

On Tuesday, 6 March 2012 at 10:19:19 UTC, Timon Gehr wrote:


This is quite close, but real support for non-nullable types means
that they are the default and checked statically, ideally using data
flow analysis.


I agree that non-nullable types should be made the default and
statically checked but data flow analysis here is redundant.
consider:
T foo = ..; // T is not-nullable
T? bar = ..; // T? is nullable
bar = foo; // legal implicit coercion T - T?
foo = bar; // compile-time type mismatch error
//correct way:
if (bar) { // make sure bar isn't null
// compiler knows that cast(T)bar is safe
foo = bar;
}



Right. This example already demonstrates some simplistic data flow
analysis.



of course we can employ additional syntax sugar such as:
foo = bar || default_value;

furthermore:
foo.method(); // legal
bar.method(); // compile-time error

it's all easily implementable in the type system.


Actually it requires some thinking because making initialization of
non-null fields safe is not entirely trivial.

For example:
http://pm.inf.ethz.ch/publications/getpdf.php/bibname/Own/id/SummersMuellerTR11.pdf


CTFE and static constructors solve that issue for static data.


I can't seem to download the PDF... it always gives me just two bytes.

But to initialize non-null fields, I suspect we would need to be able to 
do stuff like this:


class Foo
{
int dummy;
}

class Bar
{
Foo foo = new Foo();

this() { foo.dummy = 5; }
}

Which would be lowered by the compiler into this:

class Bar
{
// Assume we've already checked for bogus assignments.
// It is now safe to make this nullable.
Nullable!(Foo) foo;

this()
{
// Member initialization is done first.
foo = new Foo();

// Then programmer-supplied ctor code runs after.
foo.dummy = 5;
}
}

I remember C# being able to do this.  I never understood why D doesn't 
allow this.  Without it, I have to repeat myself a lot, and that is just 
wrong ;).  Allowing this kind of initialization might also make it 
possible for us to have zero-argument struct constructors.


Re: dereferencing null

2012-03-06 Thread Walter Bright

On 3/6/2012 5:29 PM, Chad J wrote:

But what do you say to the notion of isolation? someFunc is isolated from
riskyShenanigans becuase it /knows/ what state is touched by riskyShenanigans.
If riskyShenanigans does something strange and unexpected, and yes, it does have
a bug in it, then I feel that someFunc should be able to reset the state touched
by riskyShenanigans and continue.



That's the theory. But in practice, when you get a seg fault, there's (at 
minimum) a logical error in your program, and it is in an undefined state. Since 
memory is all shared, you have no idea whether that error is isolated or not, 
and you *cannot* know, because there's a logic error you didn't know about.


Continuing on after the program has entered an unknown an undefined state is 
just a recipe for disaster.


Re: dereferencing null

2012-03-06 Thread H. S. Teoh
On Tue, Mar 06, 2012 at 08:29:35PM -0500, Chad J wrote:
[...]
 But what do you say to the notion of isolation?  someFunc is
 isolated from riskyShenanigans becuase it /knows/ what state is
 touched by riskyShenanigans.  If riskyShenanigans does something
 strange and unexpected, and yes, it does have a bug in it, then I
 feel that someFunc should be able to reset the state touched by
 riskyShenanigans and continue.

 The thing I find really strange here is that there's this belief
 that if feature A is buggy then the unrelated feature B shouldn't
 work either. Why?  Shouldn't the user be able to continue using
 feature B?

If feature A is buggy and the user is trying to use it, then there's a
problem. If the user doesn't use feature A or knows that feature A is
buggy and so works around it, then feature A doesn't (shouldn't) run and
won't crash.


 Btw, crashing a program is bad.  That can lose data that the user
 has entered but not yet stored.  I should have a very good reason
 before I let this happen.

I don't know what your software design is, but when I write code, if
there is the possibility of data loss, I always make the program backup
the data at intervals. I don't trust the integrity of user data after a
major problem like dereferencing a null pointer happens. Obviously
there's a serious logic flaw in the program that led to this, so all
bets are off as to whether the user's data is even usable.


 It would also be extremely frustrating for a user to have a program
 become crippled because some feature they don't even use will
 occasionally dereference null and crash the thing.  Then they have
 to wait for me to fix it, and I'm busy, so it could be awhile.

The fact that the unused feature running even though the user isn't
using it is, to me, a sign that something like a null pointer
dereference should be fatal, because it means that what you assumed the
unused feature was doing before in the background was consistent, but it
turns out to be false, so who knows what else it has been doing wrong
before it hit the null pointer. I should hate for the program to
continue running after that, since consistency has been compromised;
continuing will probably only worsen the problem.


 My impression so far is that this hinges on some kind of where
 there's one, there's more argument.  I am unconvinced because
 programs tend to have bugs anyways.  riskyShenanigans doing a
 null-dereference once doesn't mean it's any more likely to produce
 corrupt results the rest of the time: it can produce corrupt results
 anyways, because it is a computer program written by a fallible
 human being.  Anyone trying to be really careful should validate the
 results in someFunc.

It sound like what you want is some kind of sandbox isolation function,
and null pointers are just the most obvious problem among other things
that could go wrong.

We could have a std.sandbox module that can run some given code (say
PossiblyBuggyFeatureA) inside a sandbox, so that if it dereferences a
null pointer, corrupts memory, or whatever, it won't affect
UnrelatedFeatureB which runs in a different sandbox, or the rest of the
system. This way you can boldly charge forward in spite of any problems,
because you know that only the code inside the sandbox is in a bad
state, and the rest of the program (presumably) is still in good working
condition.

In Linux this is easily implemented by fork() and perhaps chroot() (if
you're *really* paranoid) and message-passing (so the main program is
guaranteed to have no corruption even when BadPluginX goes crazy and
starts trashing memory everywhere). I don't know about Windows, but I
assume there is some way to do sandboxing as well.


T

-- 
Customer support: the art of getting your clients to pay for your own 
incompetence.


Re: dereferencing null

2012-03-06 Thread bearophile
Chad J:

 I can't seem to download the PDF... it always gives me just two bytes.
 
 But to initialize non-null fields, I suspect we would need to be able to 
 do stuff like this:

There are some links here:
http://d.puremagic.com/issues/show_bug.cgi?id=4571

Bye,
bearophile


Re: dereferencing null

2012-03-06 Thread Sean Kelly
On Mar 6, 2012, at 6:29 PM, Walter Bright newshou...@digitalmars.com wrote:

 On 3/6/2012 5:29 PM, Chad J wrote:
 But what do you say to the notion of isolation? someFunc is isolated from
 riskyShenanigans becuase it /knows/ what state is touched by 
 riskyShenanigans.
 If riskyShenanigans does something strange and unexpected, and yes, it does 
 have
 a bug in it, then I feel that someFunc should be able to reset the state 
 touched
 by riskyShenanigans and continue.
 
 
 That's the theory. But in practice, when you get a seg fault, there's (at 
 minimum) a logical error in your program, and it is in an undefined state. 
 Since memory is all shared, you have no idea whether that error is isolated 
 or not, and you *cannot* know, because there's a logic error you didn't know 
 about.

Minor point, but some apps are designed such that segfaults are intended. I 
worked on a DB that dynamically mapped memory in the segfault handler and then 
resumed execution.  Since D is a systems languages, very few assumptions can be 
made about error conditions. 

Re: dereferencing null

2012-03-06 Thread Walter Bright

On 3/6/2012 8:05 PM, Walter Bright wrote:

What I'm talking about is the idea that one can recover from seg faults
resulting from program bugs.


I've written about this before, but I want to emphasize that attempting to 
recover from program BUGS is the absolutely WRONG way to go about writing 
fail-safe, critical, fault-tolerant software.


Re: dereferencing null

2012-03-06 Thread Walter Bright

On 3/6/2012 7:08 PM, Sean Kelly wrote:

Minor point, but some apps are designed such that segfaults are intended. I
worked on a DB that dynamically mapped memory in the segfault handler and
then resumed execution.  Since D is a systems languages, very few assumptions
can be made about error conditions.


Yes, and I've written a GC implementation that relied on intercepting invalid 
page writes to construct its list of 'dirty' pages.


There's nothing in D preventing one from doing that, although for sure such code 
will be very, very system specific.


What I'm talking about is the idea that one can recover from seg faults 
resulting from program bugs.


Re: dereferencing null

2012-03-06 Thread Sean Kelly
Oh alright. Then we're in complete agreement. 

On Mar 6, 2012, at 8:05 PM, Walter Bright newshou...@digitalmars.com wrote:

 On 3/6/2012 7:08 PM, Sean Kelly wrote:
 Minor point, but some apps are designed such that segfaults are intended. I
 worked on a DB that dynamically mapped memory in the segfault handler and
 then resumed execution.  Since D is a systems languages, very few assumptions
 can be made about error conditions.
 
 Yes, and I've written a GC implementation that relied on intercepting invalid 
 page writes to construct its list of 'dirty' pages.
 
 There's nothing in D preventing one from doing that, although for sure such 
 code will be very, very system specific.
 
 What I'm talking about is the idea that one can recover from seg faults 
 resulting from program bugs.


Re: dereferencing null

2012-03-05 Thread Jacob Carlborg

On 2012-03-05 07:25, Walter Bright wrote:

On 3/4/2012 6:31 PM, Chad J wrote:

class Bar
{
int foo;
}

void main()
{
Bar bar;
try {
bar.foo = 5;
} catch ( Exception e ) {
writefln(%s,e);
}
}

DMD 2.057 on Gentoo Linux, compiled with -g -debug. It prints this:
Segmentation fault

Very frustrating!


This is what I get (I added in an import std.stdio;):

dmd foo -gc
gdb foo
GNU gdb (GDB) 7.2-ubuntu
Copyright (C) 2010 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later
http://gnu.org/licenses/gpl.html
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type show copying
and show warranty for details.
This GDB was configured as x86_64-linux-gnu.
For bug reporting instructions, please see:
http://www.gnu.org/software/gdb/bugs/...
Reading symbols from /home/walter/cbx/mars/foo...done.
(gdb) run
Starting program: /home/walter/cbx/mars/foo
[Thread debugging using libthread_db enabled]

Program received signal SIGSEGV, Segmentation fault.
0x00401e45 in D main () at foo.d:13
13 bar.foo = 5;
(gdb) bt
#0 0x00401e45 in D main () at foo.d:13
#1 0x0040aa9b in rt.dmain2.main() ()
#2 0x00636010 in ?? ()
#3 0x77fdeae0 in ?? ()
#4 0x7fffeb30 in ?? ()
#5 0x7fffea00 in ?? ()
#6 0x0040a41b in rt.dmain2.main() ()
#7 0x0001 in ?? ()
#8 0x0019 in ?? ()
#9 0x00636020 in ?? ()
#10 0x7fffeb30 in ?? ()
#11 0x77ffe4c0 in ?? ()
#12 0x7fffe8b0 in ?? ()
#13 0x7fffeb30 in ?? ()
#14 0x7fffea30 in ?? ()
#15 0x0040aaee in rt.dmain2.main() ()
#16 0x0040aa84 in rt.dmain2.main() ()
#17 0x7fffeb30 in ?? ()
#18 0x7fffea80 in ?? ()
#19 0x0040a41b in rt.dmain2.main() ()
#20 0x0001 in ?? ()
#21 0x0019 in ?? ()
#22 0x00636020 in ?? ()
#23 0x0001 in ?? ()
#24 0x00636020 in ?? ()
#25 0x7fffee01 in ?? ()
#26 0x7fffeb30 in ?? ()
#27 0x7fffeb30 in ?? ()
#28 0x0040a3b3 in main ()
(gdb)

By running it under gdb (the debugger), it tells me what file and line
it failed on, and gives a lovely stack trace.

There really are only 3 gdb commands you need (and the only ones I
remember):

run (run your program)
bt (print a backtrace)
quit (exit gdb)

Voila!

Also, a null pointer exception is only one of a whole menagerie of
possible hardware-detected errors. There's a limit on the compiler
instrumenting code to detect these. At some point, it really is worth
learning how to use the debugger.


Is demangling supposed to work on Mac OS X?

--
/Jacob Carlborg


Re: dereferencing null

2012-03-05 Thread David Nadlinger

On Monday, 5 March 2012 at 09:09:30 UTC, Jacob Carlborg wrote:

On 2012-03-05 07:25, Walter Bright wrote:

[…]
run (run your program)
bt (print a backtrace)
quit (exit gdb)
[…]

Is demangling supposed to work on Mac OS X?


As the D demangling support was added in GDB 7.something, 
unfortunately no, as Apple ships an ancient (customized) version.


David


Re: dereferencing null

2012-03-05 Thread Jesse Phillips

On Monday, 5 March 2012 at 00:33:18 UTC, Nathan M. Swan wrote:

On Saturday, 3 March 2012 at 02:51:41 UTC, Walter Bright wrote:
Adding in software checks for null pointers will dramatically 
slow things down.


What about the debug/release difference? Isn't the point of 
debug mode to allow checks such as assert, RangeError, etc? 
Segmentation fault: 11 prevents memory from corrupting, but 
it isn't helpful in locating a bug.


It can in linux. Enable debug symbols, and core dumps, open in gdb

$ ulimit -c unlimited
$ dmd files.d -gc
$ gdb ./files core


Re: dereferencing null

2012-03-05 Thread Walter Bright

On 3/4/2012 11:50 PM, Chad J wrote:

Problems:
- I have to rerun the program in a debugger to see the stack trace. This is a
slow workflow. It's a big improvement if the segfault is hard to find, but only
a small improvement if the segfault is easy to find. Very bad if I'm prototyping
experimental code and I have a bunch to go through.


I don't get this at all. I find it trivial to run the program with a debugger:

  gdb foo
  run

that's it.


- It only gives one line number. I imagine there's a way to get it to spill the
rest? At least it's the most important line number. Nonetheless, I commonly
encounter cases where the real action is happening a few levels into the stack,
which means I want to see ALL the line numbers /at one time/.


That's because the runtime library is compiled without debug symbols in it. If 
it was compiled with -g, the line numbers would be there. You of course can 
compile the library that way if you want. Debug symbols substantially increase 
your program size.




- As I mentioned in another post, it is unreasonable to expect others to run
your programs in a debugger. I like it when my users can send me stacktraces.
(And they need to have ALL the line numbers displayed with no extra coercion.)
There are a number of occasions where I don't even need to ask how to reproduce
the bug, because I can just tell by looking at the trace. Super useful!


I agree that customers emailing you a stack trace is a reasonable point. Andrei 
also brought up the point of the problems with using a debugger on a remote 
server machine.




I wouldn't even expect ALL hardware errors to be instrumented in the compiler.
At least get the common ones. Null dereference is remarkably common. I can't
actually think of others I care about right now. Array boundary errors and
assertions already seem to have their own exceptions now; they were great pests
back in the day when this was not so.


No hardware support for them, so no choice.



The error messages could use a lot of work
though. (Range Violation should print the index used and the index boundaries,
and simpler assertions such as equality should print the values of their 
operands.)


The added bloat for this would be substantial.



I'm pretty sure other languages like C# and Java get this right. Haven't used
those two in a while though. Haxe... totally got this right. Also Actionscript 3
by proxy. Hell, even Synergy/DE, the DIBOL (!!) derivative that I use at work,
/gets this right/. I get stacktraces for null dereferences in these languages.
It's /really/ convenient and useful. I consider D to be very backwards in this
regard.


Notably, C and C++ do not do what you suggest.


Re: dereferencing null

2012-03-05 Thread Sandeep Datta


No hardware support for them, so no choice.



I am just going to leave this here...

*Fast Bounds Checking Using Debug Register*

http://www.ecsl.cs.sunysb.edu/tr/TR225.pdf


Re: dereferencing null

2012-03-05 Thread deadalnix

Le 03/03/2012 21:10, Timon Gehr a écrit :

On 03/03/2012 09:00 PM, deadalnix wrote:

Le 03/03/2012 20:06, Walter Bright a écrit :

On 3/3/2012 2:13 AM, bearophile wrote:

Walter:


Adding in software checks for null pointers will dramatically slow
things
down.


Define this use of dramatically in a more quantitative and objective
way,
please. Is Java dramatically slower than C++/D here?


You can try it for yourself. Take some OOP code of yours, and insert a
null check in front of every dereference of the class handle.


Why would you want to check every time ? You program will get a signal
from the system if it try to deference a null pointer, so thing can be
done in the signal handler, and no cost is involved.


The signal will likely be the same for the following two code snippets:

void main(){
Object o;
o.toString();
}

void main(){
*cast(int*)0xDEADBEEF = 1337;
}


How to detect whether or not the access violation was actually caused by
a null pointer?


Signal hanlder are provided a - system dependant - structure that 
contains such informations.


This is used to detect stackoverflow as well a null pointer deference. 
Lib like libsigsegv can help a lot to implement such a thing.


Re: dereferencing null

2012-03-05 Thread Jacob Carlborg

On 2012-03-05 11:38, Walter Bright wrote:

On 3/4/2012 11:50 PM, Chad J wrote:

I'm pretty sure other languages like C# and Java get this right.
Haven't used
those two in a while though. Haxe... totally got this right. Also
Actionscript 3
by proxy. Hell, even Synergy/DE, the DIBOL (!!) derivative that I use
at work,
/gets this right/. I get stacktraces for null dereferences in these
languages.
It's /really/ convenient and useful. I consider D to be very backwards
in this
regard.


Notably, C and C++ do not do what you suggest.


Just because C and C++ do something in a certain way doesn't make it a 
valid reason to do the same thing in D.


I think this is an argument we need to stop using immediately. It just 
shows we're stuck in our ways, can't innovate and can't think for our self.


--
/Jacob Carlborg


Re: dereferencing null

2012-03-05 Thread Martin Nowak
On Mon, 05 Mar 2012 10:43:22 +0100, David Nadlinger s...@klickverbot.at  
wrote:



On Monday, 5 March 2012 at 09:09:30 UTC, Jacob Carlborg wrote:

On 2012-03-05 07:25, Walter Bright wrote:

[…]
run (run your program)
bt (print a backtrace)
quit (exit gdb)
[…]

Is demangling supposed to work on Mac OS X?


As the D demangling support was added in GDB 7.something,  
unfortunately no, as Apple ships an ancient (customized) version.


David


From GDB7.3 OSX MACH-O support is somewhat fixed, but it's buggy when being
used with dmd because it doesn't relocate the __textcoal_nt sections.


Re: dereferencing null

2012-03-05 Thread Andrej Mitrovic
Personally I'd love to get more info about out-of-bounds errors. E.g.
for arrays, which index the code attempted to access, and for hashes
which key.

Sure it's easy to use an enforce, but I'd rather have that inserted in
debug builds with bounds checking anyway. For example:

void main()
{
int[int] aa;
int key = 1;
auto a = aa[key];
}

core.exception.RangeError@test(22): Range violation

That's not too much information (well there's also that stacktrace
which is still broken on XP regardless of dbghelp.dll). This is
better:

import std.exception;
import core.exception;

void main()
{
int[int] aa;
int key = 1;
enforce(key in aa, new RangeError(format(: Key %s not in hash. , key)));
auto a = aa[key];
}

core.exception.RangeError@: Key 1 not in hash. (20): Range violation

I'd rather not have to depend on debuggers or code duplication (even
mixins) for this basic information.

Side-note: RangeError is missing a constructor that takes a *message*
as the first parameter, the one that was called takes a file string
parameter. With the ctor fixed the error becomes:
core.exception.RangeError@test.d(20): Range violation: Key 1 not in hash.

That would help me so much without having to change code, recompile,
and then wait 20 seconds at runtime to reach that failing test again.


Re: dereferencing null

2012-03-05 Thread Steven Schveighoffer

On Fri, 02 Mar 2012 10:19:13 -0500, deadalnix deadal...@gmail.com wrote:


Le 02/03/2012 15:37, Jacob Carlborg a écrit :

Isn't it quite unsafe to throw an exception in a signal ?


One does not need to throw an exception.  Just print a stack trace.  I've  
advocated for this multiple times.  I agree it costs nothing to implement,  
and who cares about safety when the app is about to crash?!


The signal handler is called on top of the stack, but the information to  
retrieve the stack trace are system dependant. BTW, using lib like  
libsigsegv can help a lot to make it safe. It isn't safe ATM, but it is  
doable.


libsigsegv is used to perform custom handling of page faults (e.g. loading  
pages of memory from a database instead of the MMC).  You do not need  
libsigsegv to handle SEGV signals.


-Steve


Re: dereferencing null

2012-03-05 Thread H. S. Teoh
On Mon, Mar 05, 2012 at 02:50:25AM -0500, Chad J wrote:
[...]
 Problems:
 - I have to rerun the program in a debugger to see the stack trace.

Nope. You can run it on a dumped core.


[...]
 - It only gives one line number.  I imagine there's a way to get it to
 spill the rest?  At least it's the most important line number.
 Nonetheless, I commonly encounter cases where the real action is
 happening a few levels into the stack, which means I want to see ALL
 the line numbers /at one time/.

I use gdc, and it gives a full stack trace with line numbers on pretty
much every line.


 - As I mentioned in another post, it is unreasonable to expect
 others to run your programs in a debugger.  I like it when my users
 can send me stacktraces.  (And they need to have ALL the line
 numbers displayed with no extra coercion.)  There are a number of
 occasions where I don't even need to ask how to reproduce the bug,
 because I can just tell by looking at the trace.  Super useful!
[...]

I guess it depends on your customer base. The customers *my* company
deals with are unlikely to give any more info than it crashed. (Worse
yet, they have rather odd definitions for the word crash. I've seen an
actual case where somebody called an unexpected behaviour a crash,
when it was actually a *correct* program response to wrong user input.)
Most of them have no idea what a stacktrace is... to them it's just some
meaningless crap the computer spews out when something goes wrong --
something you want to get off the screen, out of sight, out of mind,
ASAP.  They have no concept that *somebody* might actually find this
meaningless info useful.


T

-- 
2+2=4. 2*2=4. 2^2=4. Therefore, +, *, and ^ are the same operation.


Re: dereferencing null

2012-03-05 Thread H. S. Teoh
On Mon, Mar 05, 2012 at 02:30:14PM +0100, Andrej Mitrovic wrote:
 Personally I'd love to get more info about out-of-bounds errors. E.g.
 for arrays, which index the code attempted to access, and for hashes
 which key.

Personally, I'd love to see D's added string capabilities put to good
use in *all* exception messages. It's been how many decades since the
first C compiler was written? Yet we still haven't moved on from using
static strings in Exceptions. This is silly. A file not found
exception should tell you what the offending filename is. It's as simple
as:

throw new IOException(File '%s' not found.format(filename));

A range violation should say what the offending index was:

[...]
 enforce(key in aa, new RangeError(format(: Key %s not in hash. , key)));
[...]
 core.exception.RangeError@: Key 1 not in hash. (20): Range violation

A numerical conversion error should say what the offending malformed
number was. Or at least, include the non-digit character that it choked
on.

A syntax error in getopt should tell you what the offending option was.
(How'd you like it if you ran some random program, and it says command
line error with no indication at all of what the error was?)

It's pure common sense. I mean, if the only message dmd ever gave was
syntax error without telling you *what* caused the syntax error or
*where* (file, line number, perhaps column), we'd all be beating down
Walter's door. So why should exceptions in other applications be any
different?


T

-- 
The volume of a pizza of thickness a and radius z can be described by
the following formula: pi zz a. -- Wouter Verhelst


Re: dereferencing null

2012-03-05 Thread Adam D. Ruppe

On Monday, 5 March 2012 at 06:19:53 UTC, Chad J wrote:

That's cool.  Maybe someone should stick it in Phobos?


I just made a patch and sent it up. It'll have to be
reviewed by the others, but I expect we'll have something
in std.typecons for the next release.


I also didn't know about @disabled; that's a nifty addition.


Yeah, we brought it up one of the previous null
discussions, and Walter+Andrei liked it as a general
solution to enable this and other checks, like ranged
integers.

Still somewhat new, though; havn't realized all its
potential yet.


Re: dereferencing null

2012-03-05 Thread Andrej Mitrovic
On 3/5/12, H. S. Teoh hst...@quickfur.ath.cx wrote:
snip

Yep, agreed with everything you've said.

Also, I find your message signatures amusing. :P


Re: dereferencing null

2012-03-05 Thread deadalnix

Le 05/03/2012 15:26, Steven Schveighoffer a écrit :

On Fri, 02 Mar 2012 10:19:13 -0500, deadalnix deadal...@gmail.com wrote:


Le 02/03/2012 15:37, Jacob Carlborg a écrit :

Isn't it quite unsafe to throw an exception in a signal ?


One does not need to throw an exception. Just print a stack trace. I've
advocated for this multiple times. I agree it costs nothing to
implement, and who cares about safety when the app is about to crash?!


The signal handler is called on top of the stack, but the information
to retrieve the stack trace are system dependant. BTW, using lib like
libsigsegv can help a lot to make it safe. It isn't safe ATM, but it
is doable.


libsigsegv is used to perform custom handling of page faults (e.g.
loading pages of memory from a database instead of the MMC). You do not
need libsigsegv to handle SEGV signals.

-Steve


No you don't, but if you want to know if you are facing a stackoverflow 
or a null deference for exemple, this greatly help the implementation.


Re: dereferencing null

2012-03-05 Thread Walter Bright

On 3/5/2012 4:27 AM, Jacob Carlborg wrote:

On 2012-03-05 11:38, Walter Bright wrote:

Notably, C and C++ do not do what you suggest.


Just because C and C++ do something in a certain way doesn't make it a valid
reason to do the same thing in D.

I think this is an argument we need to stop using immediately. It just shows
we're stuck in our ways, can't innovate and can't think for our self.



Doing things differently than well established practice requires a strong 
reason. There are often good reasons for that established practice that aren't 
obvious.




Re: dereferencing null

2012-03-05 Thread Walter Bright

On 3/5/2012 8:07 AM, H. S. Teoh wrote:

A file not found exception should tell you what the offending filename is.


std.file.read(adsfasdf) gives:

std.file.FileException@std\file.d(305): adsfasdf: The system cannot find the 
file specified.


Re: dereferencing null

2012-03-05 Thread H. S. Teoh
On Mon, Mar 05, 2012 at 11:06:40AM -0800, Walter Bright wrote:
 On 3/5/2012 8:07 AM, H. S. Teoh wrote:
 A file not found exception should tell you what the offending filename is.
 
 std.file.read(adsfasdf) gives:
 
 std.file.FileException@std\file.d(305): adsfasdf: The system cannot
 find the file specified.

That's good to know. I just picked file not found as my favorite
whipping boy. :-) Now we just need this consistently across all the
standard exceptions. The including the wrong parameter part, not the
whipping part.


T

-- 
Today's society is one of specialization: as you grow, you learn more
and more about less and less. Eventually, you know everything about
nothing.


Re: dereferencing null

2012-03-05 Thread H. S. Teoh
On Mon, Mar 05, 2012 at 06:12:43PM +0100, Andrej Mitrovic wrote:
[...]
 Also, I find your message signatures amusing. :P

I have a file of amusing quotes that I collected over the years from
various sources (including some not-so-funny ones I made up myself), and
a 1-line perl script hooked to my Mutt compose function that randomly
selects a quote and puts it on my signature line.  Once in a while it
can coincidentally pick a quote relevant to the actual discussion in the
message body, which makes it even funnier.


T

-- 
Laissez-faire is a French term commonly interpreted by Conservatives to
mean 'lazy fairy,' which is the belief that if governments are lazy
enough, the Good Fairy will come down from heaven and do all their work
for them.


Re: dereferencing null

2012-03-05 Thread Nick Sabalausky
Walter Bright newshou...@digitalmars.com wrote in message 
news:jj32l2$1dk$1...@digitalmars.com...
 On 3/5/2012 4:27 AM, Jacob Carlborg wrote:
 On 2012-03-05 11:38, Walter Bright wrote:
 Notably, C and C++ do not do what you suggest.

 Just because C and C++ do something in a certain way doesn't make it a 
 valid
 reason to do the same thing in D.

 I think this is an argument we need to stop using immediately. It just 
 shows
 we're stuck in our ways, can't innovate and can't think for our self.


 Doing things differently than well established practice requires a strong 
 reason. There are often good reasons for that established practice that 
 aren't obvious.


Ok, then what's the strong reason for abandoning the practice here that's 
been well established by damn near everying other than C/C++?




Re: dereferencing null

2012-03-05 Thread Nick Sabalausky
Walter Bright newshou...@digitalmars.com wrote in message 
news:jj252v$15vf$1...@digitalmars.com...
 On 3/4/2012 11:50 PM, Chad J wrote:
 Problems:
 - I have to rerun the program in a debugger to see the stack trace. This 
 is a
 slow workflow. It's a big improvement if the segfault is hard to find, 
 but only
 a small improvement if the segfault is easy to find. Very bad if I'm 
 prototyping
 experimental code and I have a bunch to go through.

 I don't get this at all. I find it trivial to run the program with a 
 debugger:

   gdb foo
   run

 that's it.


Not all software is minimally-interactive CLI.

 I'm pretty sure other languages like C# and Java get this right. Haven't 
 used
 those two in a while though. Haxe... totally got this right. Also 
 Actionscript 3
 by proxy. Hell, even Synergy/DE, the DIBOL (!!) derivative that I use at 
 work,
 /gets this right/. I get stacktraces for null dereferences in these 
 languages.
 It's /really/ convenient and useful. I consider D to be very backwards in 
 this
 regard.

 Notably, C and C++ do not do what you suggest.

So what? C and C++ suck ass. That's why D exists.




Re: dereferencing null

2012-03-05 Thread Jacob Carlborg

On 2012-03-05 20:02, Walter Bright wrote:

On 3/5/2012 4:27 AM, Jacob Carlborg wrote:

On 2012-03-05 11:38, Walter Bright wrote:

Notably, C and C++ do not do what you suggest.


Just because C and C++ do something in a certain way doesn't make it a
valid
reason to do the same thing in D.

I think this is an argument we need to stop using immediately. It just
shows
we're stuck in our ways, can't innovate and can't think for our self.



Doing things differently than well established practice requires a
strong reason. There are often good reasons for that established
practice that aren't obvious.


Yeah, C and C++ might not do what's suggested but basically all other 
languages do it.


--
/Jacob Carlborg


Re: dereferencing null

2012-03-05 Thread Nick Sabalausky
Adam D. Ruppe destructiona...@gmail.com wrote in message 
news:ewuffoakafwmuybbz...@forum.dlang.org...
 On Monday, 5 March 2012 at 03:24:32 UTC, Chad J wrote:
 It's that I simply cannot expect users to run my code in a debugger.

 :) I'm lucky if I can get more from my users than
 the site doesn't work!


I *hate* those reports!!

But they get worse than that: Fairly soon after retaliating to a Durr...It 
don't work! email with a nice formal (and painfully friendly) explanation 
of how and why to give me useful reports (which he even acknowledged as 
being a good point), I got from the same damn person (ie *the top guy in 
charge of the project in question!*): So-and-so person told me that one of 
*their* people told them that the site didn't work when they tried it last 
week. WHAT THE FUCKING FUCK?!?!?! Shit like that I'm inclined to just blame 
on user error. I mean, crap, with a report like that, how am I supposed to 
know they spelled the URL right or even had a fucking internet connection at 
all? Or even a damn computer.

I swear, as soon as a computer enters the picture, most people turn shit 
stupid (well, more stupid than usual): I can't imagine that *even these 
people* would go up to an auto mechanic as say Driving to Detroit didn't 
work! But that's exactly the crap I have to put up with. And then *I* have 
to (politely!) explain to these shitheads how to not be a moron...only to 
have them come back and pull the same shit two weeks later? Fuck, and people 
wonder why I hate humans.




Re: dereferencing null

2012-03-05 Thread Nick Sabalausky
Walter Bright newshou...@digitalmars.com wrote in message 
news:jiunst$qrm$1...@digitalmars.com...

 3. Intercepting and recovering from seg faults, div by 0, etc., all sounds 
 great on paper. In practice, it is almost always wrong. The only exception 
 (!) to the rule is when sandboxing a plugin (as you suggested).


The purpose of catching exceptions is to respond to a condition. Recovery is 
merely *one* such type of response.




Re: dereferencing null

2012-03-05 Thread Steven Schveighoffer

On Mon, 05 Mar 2012 13:29:09 -0500, deadalnix deadal...@gmail.com wrote:


Le 05/03/2012 15:26, Steven Schveighoffer a écrit :
On Fri, 02 Mar 2012 10:19:13 -0500, deadalnix deadal...@gmail.com  
wrote:



Le 02/03/2012 15:37, Jacob Carlborg a écrit :

Isn't it quite unsafe to throw an exception in a signal ?


One does not need to throw an exception. Just print a stack trace. I've
advocated for this multiple times. I agree it costs nothing to
implement, and who cares about safety when the app is about to crash?!


The signal handler is called on top of the stack, but the information
to retrieve the stack trace are system dependant. BTW, using lib like
libsigsegv can help a lot to make it safe. It isn't safe ATM, but it
is doable.


libsigsegv is used to perform custom handling of page faults (e.g.
loading pages of memory from a database instead of the MMC). You do not
need libsigsegv to handle SEGV signals.

-Steve


No you don't, but if you want to know if you are facing a stackoverflow  
or a null deference for exemple, this greatly help the implementation.


It's somewhat off the table with it's GPL license.  But even so, I don't  
see that it helps here, we are not looking to continue execution, just  
more information on the crash than Segmentation Fault.


-Steve


Re: dereferencing null

2012-03-05 Thread Jérôme M. Berger
Steven Schveighoffer wrote:
 On Mon, 05 Mar 2012 13:29:09 -0500, deadalnix deadal...@gmail.com wrote:
 
 Le 05/03/2012 15:26, Steven Schveighoffer a écrit :
 On Fri, 02 Mar 2012 10:19:13 -0500, deadalnix deadal...@gmail.com
 wrote:

 Le 02/03/2012 15:37, Jacob Carlborg a écrit :
 Isn't it quite unsafe to throw an exception in a signal ?

 One does not need to throw an exception. Just print a stack trace. I've
 advocated for this multiple times. I agree it costs nothing to
 implement, and who cares about safety when the app is about to crash?!

 The signal handler is called on top of the stack, but the information
 to retrieve the stack trace are system dependant. BTW, using lib like
 libsigsegv can help a lot to make it safe. It isn't safe ATM, but it
 is doable.

 libsigsegv is used to perform custom handling of page faults (e.g.
 loading pages of memory from a database instead of the MMC). You do not
 need libsigsegv to handle SEGV signals.

 -Steve

 No you don't, but if you want to know if you are facing a
 stackoverflow or a null deference for exemple, this greatly help the
 implementation.
 
 It's somewhat off the table with it's GPL license.  But even so, I don't
 see that it helps here, we are not looking to continue execution, just
 more information on the crash than Segmentation Fault.
 
I wonder if deadalnix isn't confusing with libSegFault which is
part of GNU's glibc: http://blog.andrew.net.au/2007/08/15/

Jerome

PS: Sorry if this message is sent twice, there was an error the
first time and it looks like it didn't get through...
-- 
mailto:jeber...@free.fr
http://jeberger.free.fr
Jabber: jeber...@jabber.fr



signature.asc
Description: OpenPGP digital signature


Re: dereferencing null

2012-03-05 Thread Steven Schveighoffer
On Mon, 05 Mar 2012 05:38:20 -0500, Walter Bright  
newshou...@digitalmars.com wrote:



On 3/4/2012 11:50 PM, Chad J wrote:

Problems:
- I have to rerun the program in a debugger to see the stack trace.  
This is a
slow workflow. It's a big improvement if the segfault is hard to find,  
but only
a small improvement if the segfault is easy to find. Very bad if I'm  
prototyping

experimental code and I have a bunch to go through.


I don't get this at all. I find it trivial to run the program with a  
debugger:


   gdb foo
   run

that's it.


This argument continually irks me to no end.  It seems like the trusty  
(rusty?) sword you always pull out when defending the current behavior,  
but it falls flat on its face when a programmer is faced with a Seg Fault  
that has occurred on a program that was running for several days/weeks,  
possibly not in his development environment, and now he must run it via a  
debugger to wait another several days/weeks to (hopefully) get the same  
error.


Please stop using this argument, it's only valid on trivial bugs that  
crash immediately during development.


I wholeheartedly agree that we should use the hardware features that we  
are given, and that NullPointerException is not worth the bloat.  But we  
should be doing *something* better than just printing Segmentation Fault.


-Steve


Re: dereferencing null

2012-03-05 Thread H. S. Teoh
On Mon, Mar 05, 2012 at 05:31:34PM -0500, Steven Schveighoffer wrote:
[...]
 I wholeheartedly agree that we should use the hardware features that
 we are given, and that NullPointerException is not worth the bloat.
 But we should be doing *something* better than just printing
 Segmentation Fault.
[...]

On Linux, you can catch SIGSEGV and print a stacktrace in the signal
handler. This is pretty standard procedure.

In theory, we *could* have druntime install a handler for SIGSEGV upon
program startup that prints a stacktrace and exits (or do whatever the
equivalent is on Windows, if compiled on Windows).


T

-- 
Let's eat some disquits while we format the biskettes.


Re: dereferencing null

2012-03-05 Thread Jonathan M Davis
On Monday, March 05, 2012 15:05:57 Nick Sabalausky wrote:
 Walter Bright newshou...@digitalmars.com wrote in message
 news:jiunst$qrm$1...@digitalmars.com...
 
  3. Intercepting and recovering from seg faults, div by 0, etc., all sounds
  great on paper. In practice, it is almost always wrong. The only exception
  (!) to the rule is when sandboxing a plugin (as you suggested).
 
 The purpose of catching exceptions is to respond to a condition. Recovery is
 merely *one* such type of response.

If a segfault were turned into an exception of some kind, then it would 
definitely need to be an Error like AssertError or OutOfMemoryError, not a type 
derived from Exception. And I'd argue that a NullPointerException should 
really be a NullPointerError if such is ever added.

- Jonathan M Davis


Re: dereferencing null

2012-03-05 Thread Adam D. Ruppe

On Monday, 5 March 2012 at 22:50:46 UTC, H. S. Teoh wrote:
In theory, we *could* have druntime install a handler for 
SIGSEGV upon program startup that prints a stacktrace and

exits


This sounds like a good idea to me.


(or do whatever the
equivalent is on Windows, if compiled on Windows).


On Windows, hardware exceptions are turned into D exceptions
by the SEH system.

The source is in druntime/src/rt/deh.d

You can catch null pointers on Windows if you want; the
OS makes this possible.


Re: dereferencing null

2012-03-05 Thread Andrei Alexandrescu

On 3/5/12 2:31 PM, Steven Schveighoffer wrote:

On Mon, 05 Mar 2012 05:38:20 -0500, Walter Bright
newshou...@digitalmars.com wrote:

I don't get this at all. I find it trivial to run the program with a
debugger:

gdb foo
run

that's it.


This argument continually irks me to no end. It seems like the trusty
(rusty?) sword you always pull out when defending the current behavior,
but it falls flat on its face when a programmer is faced with a Seg
Fault that has occurred on a program that was running for several
days/weeks, possibly not in his development environment, and now he must
run it via a debugger to wait another several days/weeks to (hopefully)
get the same error.

Please stop using this argument, it's only valid on trivial bugs that
crash immediately during development.


I second that.

Andrei




  1   2   >