Re: debugger blues

2016-04-29 Thread cy via Digitalmars-d

On Saturday, 2 April 2016 at 01:13:54 UTC, Alex Parrill wrote:


But it's not overly hard to implement your own print function:


The biggest problem is that I wanted the file and line 
information in my print function, which just added a lot of 
boilerplate that the logger already did.

prefix.put(moduleName);
prefix.put(':');
prefix.put(to!string(line));
prefix.put(' ');
...and such.

But yeah it's not too hard to implement.
https://github.com/cyisfor/story-generator/blob/master/source/print.d


Re: debugger blues

2016-04-01 Thread Alex Parrill via Digitalmars-d
Comparing a logging framework with a basic print function is not 
a fair comparison. I'd like to point out that Python's logging 
module[1] also takes format strings.


So this really is just an argument of D's writeln vs Python's 
print. In which case, this seems like a small thing to get upset 
over. Yes, implicit spacing is convenient, but in some cases it 
isn't. It's a fairly arbitrary choice. I'd argue that D's writeln 
follows Python's philosophy of "Explicit is better than implicit" 
better than Python does.


But it's not overly hard to implement your own print function:

void print(Args...)(Args args) {
foreach(i, arg; args) {
if(i != 0) write(" ");
write(arg);
}
writeln();
}

[1] https://docs.python.org/3/library/logging.html


Re: debugger blues

2016-04-01 Thread ag0aep6g via Digitalmars-d

On 31.03.2016 04:52, cy wrote:

warningf("%s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s
%s","I","really","don't","know","how","straightforward","that","is","if","you","have","to","manually","count","every","argument","you","pass.");



import std.range: only;
warningf("%-(%s %)", only("foo", "bar", "baz"));


I was also going to suggest joiner:


import std.algorithm: joiner;
warning(only("foo", "bar", "baz").joiner(" "));


But warning goes crazy on that. std.experimental.logger seems to have a 
problem with dchar.


Re: debugger blues

2016-03-30 Thread cy via Digitalmars-d

On Tuesday, 29 March 2016 at 23:49:21 UTC, Marco Leise wrote:

It is straightforward to put spaces between arguments:
warningf("%s %s %s", "puts", "spaces", "inbetween");


warningf("%s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s 
%s","I","really","don't","know","how","straightforward","that","is","if","you","have","to","manually","count","every","argument","you","pass.");



If you refer to the common headers that go before each message,


No, I'm referring to concatenating all the arguments before 
passing the message to the logger.



WTF? :p


It's not that crazy an idea. If something takes multiple strings 
and doesn't format them the way you like it, then you write a 
wrapper around it that takes multiple strings, formats them, then 
passes the one string result downward. Just doesn't work so well 
with logging, since __file__ and the like need to be passed 
along, so they end up adding up a lot of boilerplate.


Anyway, I figured out a way to do it. I thought formattedWrite 
was just concatenating the arguments with an Appender!string, but 
I was wrong. It actually is taking an output range that calls 
logMsgPart for each of the arguments. So... I have nothing to 
complain about really. What I thought wasn't there, I actually 
just missed seeing.


import std.experimental.logger;
import std.stdio;

class MyLogger: Logger {
  bool started;
  this() {
super(LogLevel.warning);
started = false;
  }
  override
  void writeLogMsg(ref LogEntry payload) {
writeln("uhhh");
  }
  override void logMsgPart(const(char)[] msg) {
if(msg.length == 0) return;
if(started)
  write(" ");
else
  started = true;
write(msg);
  }
  override void finishLogMsg() {
started = false;
writeln("");
  }
}

void main() {
  (new MyLogger()).warning("is","this","a","good","idea?");
  (new MyLogger()).warning("python","ruined","me");
}


Re: debugger blues

2016-03-29 Thread Marco Leise via Digitalmars-d
Am Mon, 28 Mar 2016 19:29:38 +
schrieb cy :

> On Sunday, 27 March 2016 at 15:40:47 UTC, Marco Leise wrote:
> > Is it just me? I've never heard of a programming environment, 
> > let alone a system programming language providing that 
> > information.
> 
> Well, not by default certainly. It is a bit pie-in-the-sky […].

At first you framed it like it was something to be expected in
a PL. As a pie-in-the-sky for DMD on the other hand I agree
with you. Maybe it is enough that GDC provides this feature.
Or maybe you could turn the idea into a DIP (with GCC as the
reference implementation) so eventually DMD and LDC can provide
this as well.

> > "DOESN'T LET YOU PUT SPACES BETWEEN THE ARGUMENTS" is just 
> > silly and factually wrong.
> 
> No, it's factually true. You can provide arguments that have 
> spaces in them, but there is no way to put spaces between the 
> arguments to your logging function. I would expect that the 
> logger would be called with the arguments provided, but instead 
> the logging code uses a private function to stringify and 
> concatenate all the arguments, and provides it to the logger as 
> one single opaque string. This is certainly something that could 
> be improved.

It is straightforward to put spaces between arguments:
warningf("%s %s %s", "puts", "spaces", "inbetween");

If you refer to the common headers that go before each
message, those are indeed not configurable for existing Logger
implementations. Swapping them out is not complicated though:

import std.experimental.logger;
import std.stdio;

stdThreadLocalLog = new class FileLogger
{
this() { super(stderr, LogLevel.all); }

override protected void beginLogMsg(
string file, int line, string
funcName, string prettyFuncName,
string moduleName, LogLevel logLevel,
Tid threadId, SysTime timestamp,
Logger logger)
{
import std.string : lastIndexOf;
auto idx1 = file.lastIndexOf('/');
auto idx2 = funcName.lastIndexOf('.');
formattedWrite(this.file.lockingTextWriter(),
"%s %s %s %u ", timestamp,
file[idx1 + 1 .. $],
funcName[idx2 + 1 .. $], line);
}
};

warningf("%s", "<- the header now has spaces instead of ':' in it");

You could also make 'beginLogMsg' call a user provided
delegate for formatting to freely change the looks at runtime.
 
> What I did was write my own logging framework, that joins 
> arguments with spaces in between, and provides that as a single 
> argument to std.experimental.logging. But that requires me to 
> duplicate all the template boilerplate (func = __func__, file = 
> __file__, line = __line__ etc) so all the code in 
> std.experimental.logging to do that can't be used, reducing 
> std.experimental.logging to basically nothing other than writeln.

WTF? :p
If you wonder why some feature is not provided in the default
implementation, the answer is likely that Logger was meant to
be as light-weight as possible with the option to completely
carve it out and re-implement it. For example, if the header
could be formatted with a format string, "%s" would have been
the only option for the time stamp.

> > If you ask for a *guarantee* of no copy on struct return, then 
> > you are right.
> 
> I wish I was right. There are still some gotchas there, that I 
> don't fully understand. Things like:
> > BigStruct ret = returnsBigStructToo();
> 
> look the same as things like:
> > BigStruct ret = returnedbigstruct;
> 
> but the latter is actually a copy. D making paretheses optional 
> for properties makes it even more confusing.
> 
> > A a = b.myA // copy or emplacement?

I believe the idea is that to copy or not to copy a struct is
just an optimization step and in cases where this strictly
must not happen @disable this(this); catches all code that
would need to perform a copy to work. Maybe you can return
your structs by reference or pointer? It is hard to tell
without seeing the code, how it could be refactored with
Dlang's design choices in mind.

> But even taking that into account, I've had mysterious situations 
> where the pointer to a returned structure changed, from within 
> the function to without, without any apparant copying going on.

Be assured that if that happens without this(this) being
called, it is worth a bug report.



Re: debugger blues

2016-03-29 Thread Iain Buclaw via Digitalmars-d
On 28 March 2016 at 21:29, cy via Digitalmars-d  wrote:

> On Sunday, 27 March 2016 at 15:40:47 UTC, Marco Leise wrote:
>
>> Is it just me? I've never heard of a programming environment, let alone a
>> system programming language providing that information.
>>
>
> Well, not by default certainly. It is a bit pie-in-the-sky, but only
> because it slows everything down. It's got the same cost as profiling. Many
> languages, even C in some cases, have support for this. With gcc for
> instance, if you use -finstrument-functions then it calls
> __cyg_profile_func_enter before every function call and
> __cyg_profile_func_exit afterwards. That can be used to accumulate _totals_
> of how many times a function was called (profiling) but it can also just
> dump the called functions in order.
>
> I certainly would be shocked as heck if a debugger could take
> non-instrumented code and add all that tracing and/or profiling stuff, but
> stranger things have happened in the murky realm of code debugging.
>
>
Most language agnostic features of gcc are possible in gdc too.  Coverage
and instrumentation come for free.


Re: debugger blues

2016-03-28 Thread cy via Digitalmars-d

On Sunday, 27 March 2016 at 15:40:47 UTC, Marco Leise wrote:
Is it just me? I've never heard of a programming environment, 
let alone a system programming language providing that 
information.


Well, not by default certainly. It is a bit pie-in-the-sky, but 
only because it slows everything down. It's got the same cost as 
profiling. Many languages, even C in some cases, have support for 
this. With gcc for instance, if you use -finstrument-functions 
then it calls __cyg_profile_func_enter before every function call 
and __cyg_profile_func_exit afterwards. That can be used to 
accumulate _totals_ of how many times a function was called 
(profiling) but it can also just dump the called functions in 
order.


I certainly would be shocked as heck if a debugger could take 
non-instrumented code and add all that tracing and/or profiling 
stuff, but stranger things have happened in the murky realm of 
code debugging.


"DOESN'T LET YOU PUT SPACES BETWEEN THE ARGUMENTS" is just 
silly and factually wrong.


No, it's factually true. You can provide arguments that have 
spaces in them, but there is no way to put spaces between the 
arguments to your logging function. I would expect that the 
logger would be called with the arguments provided, but instead 
the logging code uses a private function to stringify and 
concatenate all the arguments, and provides it to the logger as 
one single opaque string. This is certainly something that could 
be improved.


What I did was write my own logging framework, that joins 
arguments with spaces in between, and provides that as a single 
argument to std.experimental.logging. But that requires me to 
duplicate all the template boilerplate (func = __func__, file = 
__file__, line = __line__ etc) so all the code in 
std.experimental.logging to do that can't be used, reducing 
std.experimental.logging to basically nothing other than writeln.


If you ask for a *guarantee* of no copy on struct return, then 
you are right.


I wish I was right. There are still some gotchas there, that I 
don't fully understand. Things like:

BigStruct ret = returnsBigStructToo();


look the same as things like:

BigStruct ret = returnedbigstruct;


but the latter is actually a copy. D making paretheses optional 
for properties makes it even more confusing.



A a = b.myA // copy or emplacement?


But even taking that into account, I've had mysterious situations 
where the pointer to a returned structure changed, from within 
the function to without, without any apparant copying going on. 
When member functions raise assertions if that pointer was 
different... it's just not workable. I don't actually know why 
copying is occurring in many cases, or pseudo-copying 
or...whatever, so I can't really tell you what I'm talking about 
exactly.


I should ask that as a separate question...


Re: debugger blues

2016-03-27 Thread Marco Leise via Digitalmars-d
Am Fri, 25 Mar 2016 14:15:57 +
schrieb Craig Dillabaugh :

> On Friday, 25 March 2016 at 08:14:15 UTC, Iain Buclaw wrote:
> clip
> >
> >> * a pony
> >
> > Of all points above, this is one that can actually be arranged.
> >  No joke!
> 
> I've got a Border Collie I could throw in to the mix too if that 
> would be helpful.

My sister always wanted a pony. When we got a dog, she made
him run in circles, jump hurdles and pull the sled. O.o :p

-- 
Marco



Re: debugger blues

2016-03-27 Thread Marco Leise via Digitalmars-d
Am Fri, 25 Mar 2016 09:00:06 +
schrieb cy :

> No, the stack trace is the hierarchy of functions that are 
> currently calling each other. I meant the functions that had been 
> called previously, even the ones that have returned.

Is it just me? I've never heard of a programming environment,
let alone a system programming language providing that
information. While I understand, why the solidity of DWARF
debug information is important, this seems to me like a pie in
the sky idea similar to the pony. I guess the front-end would
have to instrument code for that and the debugger is out of
the picture, but you should detail that in a DIP. It does
sound like an interesting idea to supplement existing
instrumentation for profiling in DMD.

> > I'm afraid to say that only you can improve your own printf 
> > messages.
> 
> Or, write a print function that actually puts spaces between the 
> arguments, or write a function that adds the file and line so you 
> know where the statement was written and don't have to go hunting 
> for it. Or std.experimental.logger or whatever. I'd use 
> std.experimental.logger except it DOESN'T LET YOU PUT SPACES 
> BETWEEN THE ARGUMENTS >:(
> 
> (can you tell I programmed a lot in python?)

Yes, alright, but you can probably tell that std.logger was
modeled after the existing formatting functionality of
std.file (e.g. writefln) and that was modeled after printf, so
to put spaces between the arguments you just add them to the
formatting string. Just use format strings, case solved.
Surely we can look at Python style spaces between arguments,
but "DOESN'T LET YOU PUT SPACES BETWEEN THE ARGUMENTS" is just
silly and factually wrong.

> > Use @disable this(this); in your structs.
> 
> Well, obviously. But I meant a way to specify it in the function 
> I'm writing. Like @nocopy or @move or something.

If you ask for a *guarantee* of no copy on struct return, then
you are right. In praxis, the memory for the return value is
allocated on the caller's stack and the callee writes directly
into it. No copy or copy constructor call is performed. In
addition most (all?) ABIs allow structs of 1 or 2 machine words
to be returned in registers (i.e. EAX:EDX on x86).

Proof:

BigStruct returnsBigStruct()
{
BigStruct ret = returnsBigStructToo();
ret.data[0] = 42;
return ret;
}


BigStruct returnsBigStructToo()
{
import std.range;
BigStruct ret = BigStruct( iota(20).array[0 .. 20] );
return ret;
}

struct BigStruct
{
int[20] data;

this(this)
{
import std.stdio;
writeln("I'm typically not called at all.");
}
}

void main()
{
import std.stdio;
immutable bigStruct = returnsBigStruct();
writeln( bigStruct.data );
}

-- 
Marco



Re: debugger blues

2016-03-26 Thread cy via Digitalmars-d
You know what I really want? I want to disable package:/private: 
access entirely! Since GDB is useless, I can't write assertions 
to compare the structure of two objects, without going into that 
3000 lines of code and writing a function to compare them in that 
particular fashion. Not being allowed to turn those accesses into 
warnings, or temporarily disabling them, seems a bit spiteful. It 
takes a lot of hubris for a programmer to decide that nobody else 
will ever want to do something with their code, that they didn't 
themselves anticipate.


On Friday, 25 March 2016 at 09:30:37 UTC, Vladimir Panteleev 
wrote:


"null this" is the error I'm talking about. It is coming from 
the object invariant. It's not caused by a segmentation fault 
caused by accessing a member.


It still happily allows me to pass around that null pointer as if 
it were a real object, and call member functions on that null 
pointer. It's only when it tries to access a member variable that 
it raises the error. I'm of the opinion that null should be 
categorically different from a pointer to a class or struct. 
Because when I get "null this" I have no general way to tell 
where that null pointer came from, and just have to eyeball the 
code and trace back to guess where it might have returned an 
unexpected null.


Segfaulting on a null this would be totally terrible, but 
erroring out on "null this" is still fail-slow.


Re: debugger blues

2016-03-25 Thread Craig Dillabaugh via Digitalmars-d

On Friday, 25 March 2016 at 08:14:15 UTC, Iain Buclaw wrote:
clip



* a pony


Of all points above, this is one that can actually be arranged.
 No joke!


I've got a Border Collie I could throw in to the mix too if that 
would be helpful.






Re: debugger blues

2016-03-25 Thread Adam D. Ruppe via Digitalmars-d

On Friday, 25 March 2016 at 09:12:56 UTC, cy wrote:

This sort of works:

try
throw new Exception(null);
catch (Exception e)
context = e.toString().splitLines()[1..$];


Huh, neat... I'll have to remember that.



Better yet, the trick from the end of my book still works, with 
mild adjustment:


// put this function in your helper module
string getStackTrace() {
  import core.runtime;

  version(Posix) {
// druntime cuts out the first few functions on the trace 
because they are internal
// so we'll make some dummy functions here so our actual info 
doesn't get cut

Throwable.TraceInfo f2() { return defaultTraceHandler(); }
Throwable.TraceInfo f1() { return f2(); }
auto trace = f1();
  } else {
auto trace = defaultTraceHandler();
  }

  return trace.toString();
}

// and call it like this:
void foo() {
import std.stdio;
writeln(getStackTrace());
}

void main() {
foo();
}






It will print the trace without an exception, showing this:


stacktrace.d:19 void stacktrace.foo() [0x8076aaf]
stacktrace.d:23 _Dmain [0x8076ac7]
??:? 
_D2rt6dmain211_d_run_mainUiPPaPUAAaZiZ6runAllMFZ9__lambda1MFZv 
[0x8077c32]
??:? void rt.dmain2._d_run_main(int, char**, extern (C) int 
function(char[][])*).tryExec(scope void delegate()) [0x8077b95]
??:? void rt.dmain2._d_run_main(int, char**, extern (C) int 
function(char[][])*).runAll() [0x8077bee]
??:? void rt.dmain2._d_run_main(int, char**, extern (C) int 
function(char[][])*).tryExec(scope void delegate()) [0x8077b95]

??:? _d_run_main [0x8077b1e]
??:? main [0x8076eab]
??:? __libc_start_main [0xf74fe29f]



Compile with -g to get the file and line number from your code.

You might also tweak the function to skip the last few lines too 
since they are just generic functions inside druntime itself.





string getStackTrace() {
  import core.runtime;

  version(Posix) {
// druntime cuts out the first few functions on the trace 
because they are internal
// so we'll make some dummy functions here so our actual info 
doesn't get cut

Throwable.TraceInfo f2() { return defaultTraceHandler(); }
Throwable.TraceInfo f1() { return f2(); }
auto trace = f1();
  } else {
auto trace = defaultTraceHandler();
  }

  // cut off the last 7 lines because they are internal
  // functions anyway
  import std.string;
  return join(splitLines(trace.toString())[0 .. $-7], "\n");
}



Which now leaves the output as a fairly simple:

$ ./stacktrace
stacktrace.d:20 void stacktrace.foo() [0x80780a7]
stacktrace.d:24 _Dmain [0x80780bf]



which might be pretty useful.


Re: debugger blues

2016-03-25 Thread Vladimir Panteleev via Digitalmars-d

On Friday, 25 March 2016 at 09:12:56 UTC, cy wrote:

What compiler flags did you use?


make -f posix install


I meant, which flags you used to build your program.

* catching null pointer errors earlier, instead of waiting 
until you 1) call the class function and 2) the function 
accesses a member.


Doesn't this already happen if you compile without -release?


Apparantly not, because I've never compiled without -debug, and 
I infrequently get "null this" errors after having called the 
function...


"null this" is the error I'm talking about. It is coming from the 
object invariant. It's not caused by a segmentation fault caused 
by accessing a member.




Re: debugger blues

2016-03-25 Thread cy via Digitalmars-d
On Friday, 25 March 2016 at 08:21:29 UTC, Vladimir Panteleev 
wrote:

Perhaps have a look at what etc.linux.memoryerror does.


Oh, there it is! In druntime! Oh look, inline assembler! No 
architectures outside of X86/X86_64. Manually editing the bytes 
of your stack context!


I think I'll just go cry in the shower now.

* DWARF debugging symbols that don't scramble the only program 
on earth that actually uses them.


What compiler flags did you use?


make -f posix install

...

I learned about BUILD=debug after that, but haven't tried it yet. 
Takes a _long_ time to compile phobos.



Having an up-to-date GDB might help.


And an up-to-date GCC, and my own custom version of glibc while 
I'm at it, and both GDC and DMD, and Phobos, and DRuntime.



This sort of works:

try
throw new Exception(null);
catch (Exception e)
context = e.toString().splitLines()[1..$];


Huh, neat... I'll have to remember that.

* catching null pointer errors earlier, instead of waiting 
until you 1) call the class function and 2) the function 
accesses a member.


Doesn't this already happen if you compile without -release?


Apparantly not, because I've never compiled without -debug, and I 
infrequently get "null this" errors after having called the 
function...


Calling a class method will invoke the class invariant hidden 
virtual method,


...in a struct, not a class.



Structs have this: @disable this(this);


I use that very liberally.


Re: debugger blues

2016-03-25 Thread cy via Digitalmars-d

On Friday, 25 March 2016 at 08:14:15 UTC, Iain Buclaw wrote:

Have you considered raising a bug report as the compiler asks?

http://bugzilla.gdcproject.org/


Yes, and that would be yet another gigantic software monstrosity 
that I have to compile the latest version in, and yet another 
signup process for their bug tracker, and yet another thing to 
keep track of. I'll get around to it.


The error was with just my distribution's release of GDC, so I'm 
pretty helpless to say that the bug even still exists. It was 
just a bug that made me wonder how people would even go and make 
a mistake like that.


It's called stack trace, uncaught exceptions print this 
information out.


No, the stack trace is the hierarchy of functions that are 
currently calling each other. I meant the functions that had been 
called previously, even the ones that have returned.



This is something that you can do with signal handlers.


Ah, yes the wonder of being forced to use @nogc, nothrow, and 
@system. In the very accessible and undocumented spot of 
core.sys.c.signal! And heaven help you if you're trying to signal 
a process in Microsoft.



There's more than one dwarf reader


yeah, I was exaggerating.


Again, use OS signal handlers?


I tried! You can't even allocate a mutex! And then the thread you 
tried to signal dies anyway, because the signal gets sent to all 
of them! And then your process both exits and does not exit, and 
there's a mysterious copy of it in the background, despite you 
never forking, going at 100% CPU.


A nice setup for signal handlers would be really cool. But what D 
has now is... minimal.


I'm afraid to say that only you can improve your own printf 
messages.


Or, write a print function that actually puts spaces between the 
arguments, or write a function that adds the file and line so you 
know where the statement was written and don't have to go hunting 
for it. Or std.experimental.logger or whatever. I'd use 
std.experimental.logger except it DOESN'T LET YOU PUT SPACES 
BETWEEN THE ARGUMENTS >:(


(can you tell I programmed a lot in python?)

etc.linux.memoryerror - you can use that for catching SIGSEGV 
and dumping stacktrace.


Uh... huh. I didn't know about that. Actually I still don't know 
about that. It's not in phobos that I can see.


I'd suggest that you do the same for other signals such as 
SIGKILL


Handling SIGKILL, now that would be an accomplishment!
(Friar Tuck... I am under attack!  Pray save me!)


Use @disable this(this); in your structs.


Well, obviously. But I meant a way to specify it in the function 
I'm writing. Like @nocopy or @move or something.


In the library or in your program?  Last time I checked phobos 
still has some way to go on that front.


In the library... ish. In the language. You can't pass an inout 
type as a template parameter to save it in a structure, so your 
structure can be agnostic of whether it's dealing with const or 
not, but you still have to write two identical member functions 
to set up and return that structure.


But granted that const is transitive, you should introduce it 
in a bottom up fashion.


The real problem is making code that works for both const and 
non-const, since like 99% of all code is exactly the same, just 
with "const" slapped on. What would be ideal is that you could 
label "frikkin everything" as const (except the stuff that 
actually does mutate) and the compiler would silently upgrade it 
to a mutable function if called with a mutable object, instead of 
erroring out and having to copypasta each function, to have a 
mutable version.


* it would be nice to be able to return an iterator whose 
elements are
either const or not const, using inout, instead of having to 
write the function twice.


This should be very possible, but I wouldn't know where you are 
going wrong.


inout only applies to function parameters, or function local 
variables. It so happens that a template parameter to a struct is 
outside of that, so Iterator!(inout(Item)) just flat out won't 
work.


Maybe you could define the structure inside the function, but 
then two functions couldn't share the same structure. And you 
can't define the template specialization inside the function, 
since inout can't be template parameters.



ref MyStruct() { return s; }


...you can do that? Huh.

* heap allocated structs, stack allocated classes, it would be 
nice to

have allocation strategy independent from layout strategy.

Use pointer to structs and scope classes.


I know there are ways to do it. It would be nice if those ways 
weren't so verbosely explicit, just a flag or a switch or 
something. There's been a lot of work on allocators recently, so 
I remain hopeful that struct/class usage can become allocation 
strategy agnostic.


I can not ask the hundreds of contributors to stop the 
fantastic work they are doing.


What if I say pretty please?


* a pony


Of all points above, this is one that can actually be arranged.
 No joke!


I'll 

Re: debugger blues

2016-03-25 Thread Vladimir Panteleev via Digitalmars-d

On Friday, 25 March 2016 at 05:59:01 UTC, cy wrote:
* a backtrace that displays when you hit ^C, instead of just 
silent death


Perhaps have a look at what etc.linux.memoryerror does.

* DWARF debugging symbols that don't scramble the only program 
on earth that actually uses them.


What compiler flags did you use?

Having an up-to-date GDB might help.

* better ways to report program status besides writeln("we got 
here somehow");


This sort of works:

try
throw new Exception(null);
catch (Exception e)
context = e.toString().splitLines()[1..$];

A `Thread.getStackTrace` would be nice.

* catching null pointer errors earlier, instead of waiting 
until you 1) call the class function and 2) the function 
accesses a member.


Doesn't this already happen if you compile without -release? 
Calling a class method will invoke the class invariant hidden 
virtual method, which will segfault when looking up the method in 
the vtable.


* ways to ensure that nothing is being copied, if you 
accidentally write a wrapper that creates an object instead of 
referencing it, or moving it.


Structs have this: @disable this(this);

* it would also be nice to be able to return references, 
instead of copying structs every time, or writing wrappers 
around them (which also cannot be used with inout)


You can return by ref...?

* heap allocated structs, stack allocated classes, it would be 
nice to have allocation strategy independent from layout 
strategy.


Heap allocated struct: auto s = new S;
Stack allocated class: auto c = scoped!C;



Re: debugger blues

2016-03-25 Thread Iain Buclaw via Digitalmars-d
On 25 Mar 2016 7:00 am, "cy via Digitalmars-d" 
wrote:
>
> I've been working for 3 days straight on this: the monumental task of
taking these text files and turning them into HTML. Or should I say, FML,
because FML. Why is this so hard?
>
> My code is peppered with writelns and sanity checks, none of which show
anything alarming until long after the document gets a self referential
cycle in it, and apparantly this is happening by "creating a child and
appending it to a node." Obviously that's a rare and obscure operation,
that nobody ever would think of doing.
>
> I can't do any introspection. GDB just goes belly up with DIE errors.
Trying to get non-broken DWARF information by switching to GDC, GDC goes
belly up with "internal error, please submit a bug report" and the reason
for this error is creating a module named "cross.iter" and adding a sixth
exported symbol to it.
>

Have you considered raising a bug report as the compiler asks?

http://bugzilla.gdcproject.org/

It will never get noticed or fixed otherwise.

> In reflection, what would be really nice is:
> * some way to trace function calls, to see the order of calls before the
program died.

It's called stack trace, uncaught exceptions print this information out.

> * a backtrace that displays when you hit ^C, instead of just silent death

This is something that you can do with signal handlers.

> * DWARF debugging symbols that don't scramble the only program on earth
that actually uses them.

There's more than one dwarf reader, but yeah dmd has many small things
lacking that mount up as you get more complex.

> * some way to signal the program to dump the stack frames of its threads
to a log

Again, use OS signal handlers?

> * better ways to report program status besides writeln("we got here
somehow");

I'm afraid to say that only you can improve your own printf messages.

> * catching null pointer errors earlier, instead of waiting until you 1)
call the class function and 2) the function accesses a member.

etc.linux.memoryerror - you can use that for catching SIGSEGV and dumping
stacktrace.

I'd suggest that you do the same for other signals such as SIGKILL and
SIGTERM.

> * ways to ensure that nothing is being copied, if you accidentally write
a wrapper that creates an object instead of referencing it, or moving it.

Use @disable this(this); in your structs.

> * better const support, so can minimize the amount of mutable data
involved here

In the library or in your program?  Last time I checked phobos still has
some way to go on that front.

But granted that const is transitive, you should introduce it in a bottom
up fashion.  First find all leaf functions and make them const, then work
your way up from there.

> * it would be nice to be able to return an iterator whose elements are
either const or not const, using inout, instead of having to write the
function twice.

This should be very possible, but I wouldn't know where you are going wrong.

> * it would also be nice to be able to return references, instead of
copying structs every time, or writing wrappers around them (which also
cannot be used with inout)

ref MyStruct() { return s; }

I've never tried mixing ref and inout before, so won't attempt it here.

> * heap allocated structs, stack allocated classes, it would be nice to
have allocation strategy independent from layout strategy.

Use pointer to structs and scope classes.

> * less people writing complex allocating functions as their struct init
property, and then leaving me wondering how that could possibly be
invariant.

I can not ask the hundreds of contributors to stop the fantastic work they
are doing.

> * a pony

Of all points above, this is one that can actually be arranged.  No joke!


debugger blues

2016-03-25 Thread cy via Digitalmars-d
I've been working for 3 days straight on this: the monumental 
task of taking these text files and turning them into HTML. Or 
should I say, FML, because FML. Why is this so hard?


My code is peppered with writelns and sanity checks, none of 
which show anything alarming until long after the document gets a 
self referential cycle in it, and apparantly this is happening by 
"creating a child and appending it to a node." Obviously that's a 
rare and obscure operation, that nobody ever would think of doing.


I can't do any introspection. GDB just goes belly up with DIE 
errors. Trying to get non-broken DWARF information by switching 
to GDC, GDC goes belly up with "internal error, please submit a 
bug report" and the reason for this error is creating a module 
named "cross.iter" and adding a sixth exported symbol to it.


In reflection, what would be really nice is:
* some way to trace function calls, to see the order of calls 
before the program died.
* a backtrace that displays when you hit ^C, instead of just 
silent death
* DWARF debugging symbols that don't scramble the only program on 
earth that actually uses them.
* some way to signal the program to dump the stack frames of its 
threads to a log
* better ways to report program status besides writeln("we got 
here somehow");
* catching null pointer errors earlier, instead of waiting until 
you 1) call the class function and 2) the function accesses a 
member.
* ways to ensure that nothing is being copied, if you 
accidentally write a wrapper that creates an object instead of 
referencing it, or moving it.
* better const support, so can minimize the amount of mutable 
data involved here
* it would be nice to be able to return an iterator whose 
elements are either const or not const, using inout, instead of 
having to write the function twice.
* it would also be nice to be able to return references, instead 
of copying structs every time, or writing wrappers around them 
(which also cannot be used with inout)
* heap allocated structs, stack allocated classes, it would be 
nice to have allocation strategy independent from layout strategy.
* less people writing complex allocating functions as their 
struct init property, and then leaving me wondering how that 
could possibly be invariant.

* a pony