July 27, 2012
On Friday, 27 July 2012 at 19:01:39 UTC, Namespace wrote:
> I also get null references (and every time I hate D a bit more), but mostly my classmates and other friends whom I've shown D. And most of them are already back to C++ or C#. And I can understand them.
> If you want that D is sometimes taken seriously (and it reached only if you win more people for D), then perhaps you should do something for more usability.
> Such small handy shorthands are easy to implement and even more understandable as a stacktrace.

 I've noticed when debugging the 'segfault' is rather vague, but it depends on if you have something to catch it. In some of my code I end up surrounding the main function in a try/catch wrapper that prints the appropriate data; Like using VisualD.

void main() {
  try {
    someFunc(null);
  } catch (Throwable x) {
    writeln(x);
  }
}

void someInnerFunc(Object o)
in {
  assert(o, "Yo! my object's NULL!");
}
body {
  //something
}
void someFunc(Object o) {
  someInnerFunc(o); //for stacktrace
}

core.exception.AssertError@test.d(111): Yo! my object's NULL!
----------------
c:\Users\Era\My Documents\progs\d\test.d(119): void test.someFunc(Object)
c:\Users\Era\My Documents\progs\d\test.d(103): _Dmain



change inner function to:

void someInnerFunc(Object o) {
  o.toHash;
  //something
}

object.Error: Access Violation
----------------
c:\Users\Era\My Documents\progs\d\test.d(116): void test.someFunc(Object)
c:\Users\Era\My Documents\progs\d\test.d(103): _Dmain

July 27, 2012
On Windows, an access violation (from a null pointer or other
causes) is an exception that is thrown and can even be caught.

On Linux, a segfault is a signal that just kills the program,
it doesn't work like a regular exception.


The Windows exceptions can do pretty stack traces, including
on null derefs, if you have some debugging library installed...
and I've done it before, but I don't remember the link right now.
It's something from Microsoft.
July 27, 2012
On Friday, 27 July 2012 at 19:48:33 UTC, Adam D. Ruppe wrote:
> On Windows, an access violation (from a null pointer or other
> causes) is an exception that is thrown and can even be caught.
>
> On Linux, a segfault is a signal that just kills the program,
> it doesn't work like a regular exception.

 Linux also dumps the state into a file. So I'd have to wonder what the problem was, you would have all the information at hand.
July 27, 2012
On Friday, 27 July 2012 at 19:50:46 UTC, Era Scarecrow wrote:
>  Linux also dumps the state into a file.

Only if core dumps are enabled... but I think someone did
a Linux stack trace signal handler somewhere for D, but
it never got merged into druntime. (What it'd do is print
out some info before exiting, instead of just saying
"segmentation fault". Still not an exception, but a little
more immediately helpful).
July 27, 2012
And that is the explicit way with pre- and postconditions of Java, which i want to avoid.

I see, the most of you prefer to write "try and catch" or use the java principle with explicit pre- and post conditions.
The time will show, if D get therewith enough members to get serious.
But this is what Java and C# have already.
July 27, 2012
On 07/27/12 21:48, Adam D. Ruppe wrote:
> On Windows, an access violation (from a null pointer or other causes) is an exception that is thrown and can even be caught.
> 
> On Linux, a segfault is a signal that just kills the program, it doesn't work like a regular exception.

It's not a regular D exception, but it is a signal that /can/
be caught and used to print stacktraces, file names, line numbers
etc, not to mention you optionally get a snapshot of the program
as it failed (the "core" file).

The only non-trivial part is getting at the debug info to map the
addresses to symbols. Simple quick and dirty example below, which
will not only print the address of the instruction that caused the
fault, but also the address that it tried to access, and may even
sometimes succeed in letting the program continue to run.
Making it work with a non-gdc compiler, non-x86 ISA, hooking up w/
a library to get all the symbol names and properly handling all the
required cases is left as an exercise for the reader. :)

But, no, special handling for null dereferencing in the language is *not* needed. Some more runtime support, maybe.

artur

   import std.stdio;

   template Seq(alias A, alias B, S...) {
      static if(S.length==0)
         alias Seq!(A, B, A) Seq;
      else static if (S[$-1]!=B)
         alias Seq!(A, B, S, S[$-1]+1) Seq;
      else
         alias S Seq;
   }

   struct hack {
      import core.sys.posix.ucontext, core.sys.posix.signal;
      alias int c_int;

      static:
      void* av;
      ubyte* violator;
      void*[4] trace;

      extern (C) void handler(c_int signum, siginfo_t* si, void* _ctx ) {
         auto ctx = cast(ucontext_t*)_ctx;
         av = si._sifields._sigfault.si_addr;
         version (X86) enum REG_RIP = 14;
         violator = cast(ubyte*)ctx.uc_mcontext.gregs[REG_RIP];
         ctx.uc_mcontext.gregs[REG_RIP] += inslen(violator);
         // scan and store backtrace etc.
         version (GNU) {
            import gcc.builtins;
            foreach (uint i; Seq!(0, trace.length-1))
               trace[i] = __builtin_return_address(i);
         }
         checkav(); // Not something you wanna do from a signal handler...
      }

      void register() {
         sigaction_t sa;
         sa.sa_sigaction = &handler;
         sa.sa_flags = SA_SIGINFO;
         if (sigaction(SIGSEGV, &sa, null))
            throw new Error("sigaction failed");
      }

      version (X86) size_t inslen(in ubyte* c) {
         if (c[0]==0xc6 && c[1]==0x05) return 7;
         if (c[0]==0x0f && c[1]==0xb6 && c[2]==0x4b) return 4;
         if (c[0]==0x0f && c[1]==0xb6 && c[2]==0x43) return 4;
         if (c[0]==0x0f && c[1]==0xb6) return 7;
         if (c[0]==0xa2) return 5;
         if (c[0]==0x65 && c[1]==0xc7) return 11;
         if (c[0]==0x88 && c[1]==0x4b) return 3;
         // ...
         return 1;
      }

      auto checkav() {
         if (av) {
            writefln("    0x%08x tried to access 0x%08x", violator, av);
            foreach(t; trace)
               writef("    0x%08x\n", t);
            av = null;
         }
      }
   }

   __gshared ubyte* p = null;

   int main() {
      hack.register();
      p[1] = 1; hack.checkav();
      p[2] = 2; hack.checkav();
      p[3] = 3; hack.checkav();
      p[5] = p[4]; hack.checkav();
      return p[42];
   }


July 27, 2012
Me again.
What's the matter if i write something for that shorthand and dmd has only to switch to it before the compiling begins?
My little test program works with VisualD.
I goto the build events and there i write into "Pre-Build Command":
[quote]not_null main.d #t[/quote]
and into "Post-Build Command":
[quote]del main.d
rename clone_main.d main.d[/quote]

Of course i have to find a way to generate this for all included files and not do this manually as
not_null a.d #t
not_null b.d #t

But if dmd would do this e.g. with a compiler flag like "-notnull" it would lighten my workload a lot.

Here is my current example code: http://dpaste.dzfl.pl/8d41468a

It replace Class? obj statements and generate two files. The normal file changes to valid D code which can compile. The "original" code with Class? obj statements will copied into clone_filename.d

I know it isn't perfect, but maybe it is a beginning.
July 27, 2012
On Saturday, July 28, 2012 01:00:22 Namespace wrote:
> Me again.
> What's the matter if i write something for that shorthand and dmd
> has only to switch to it before the compiling begins?

Doing stuff like that makes your code completely unportable. It's _bad_ practice. Don't go and try to redesign the language if you want to be playing nice with other people. If you can do something completely within the language, then that's different (other people may still hate what you're up to, but at least they can compile it), but don't use a preprocessor unless you really don't care about anyone else ever using your code but you, and even then, I'd argue against it, because if you get into the habit of doing that, you're screwed when you actually have to interact with other D programmers.

- Jonathan M Davis
July 27, 2012
Therefore i hope that it will be official added into D.
Otherwise of course i use it only for projects between me and my other students.

I don't know what is wrong with this shorthand. So why don't give it a try?
I'm absolutely sure that Walter will _never_ add real non-nullable references.
All what will maybe come are further structs in std.alghorithm which blows up your code as assertions even do.
July 27, 2012
I started a not null struct for phobos but then had to
move, added another job, and other real life stuff
that meant I haven't finished it yet.

Fairly usable though. Look for struct NotNull:

https://github.com/adamdruppe/phobos/blob/0c97414bb4aa3c748caa42948ffec25f8a291300/std/typecons.d

(also a pull request, but for some reason, my changes to
never updated here, so the pull request is out of date
and temporarily closed

https://github.com/D-Programming-Language/phobos/pull/477 )