www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - What is the point of nothrow?

reply Bauss <jj_1337 live.dk> writes:
What is the point of nothrow if it can only detect when Exception 
is thrown and not when Error is thrown?

It seems like the attribute is useless because you can't really 
use it as protection to write bugless, safe code since the nasty 
bugs will pass by just fine.

I'm aware that it's a feature that nothrow can throw Error, but 
it makes the attribute completely useless because you basically 
have no safety to guard against writing code that throws Error.

To an extend  safe works, but there are tons of stuff that throws 
Error which you can only detect and guard against manually.

So what is the point of nothrow when it can only detect 
exceptions you'd catch anyway.

To me it would be so much more useful if you could detect code 
that could possibly throw Error.
Jun 10 2018
next sibling parent reply Jonathan M Davis <newsgroup.d jmdavisprog.com> writes:
On Sunday, June 10, 2018 23:59:17 Bauss via Digitalmars-d-learn wrote:
 What is the point of nothrow if it can only detect when Exception
 is thrown and not when Error is thrown?

 It seems like the attribute is useless because you can't really
 use it as protection to write bugless, safe code since the nasty
 bugs will pass by just fine.

 I'm aware that it's a feature that nothrow can throw Error, but
 it makes the attribute completely useless because you basically
 have no safety to guard against writing code that throws Error.

 To an extend  safe works, but there are tons of stuff that throws
 Error which you can only detect and guard against manually.

 So what is the point of nothrow when it can only detect
 exceptions you'd catch anyway.

 To me it would be so much more useful if you could detect code
 that could possibly throw Error.
Why do you care about detecting code that can throw an Error? Errors are supposed to kill the program, not get caught. As such, why does it matter if it can throw an Error? Now, personally, I'm increasingly of the opinion that the fact that we have Errors is kind of dumb given that if it's going to kill the program, and it's not safe to do clean-up at that point, because the program is in an invalid state, then why not just print the message and stack trace right there and then kill the program instead of throwing anything? But unforntunately, that's not what happens, which does put things in the weird state where code can catch an Error even though it shouldn't be doing that. As for the benefits of nothrow, as I understand it, they're twofold: 1. You know that you don't have to worry about any Exceptions being thrown from that code. You don't have to worry about doing any exception handling or having to ensure that anything gets cleaned up because of an Exception being thrown. 2. If the compiler knows that a function can't throw an Exception, then it doesn't have to insert any of the Exception handling mechanism stuff that it normally does when a function is called. It can assume that nothing ever gets thrown. If an Error does get thrown, then none of the proper clean-up will get done (e.g. constructors or scope statements), but because an Error being thrown means that the program is in an invalid state, it's not actually safe to be doing clean-up anyway. So, the fact that a function is nothrow gives you a performance benefit, because none of that extra Exception handling stuff gets inserted. How large a benefit that is in practice, I don't know, but it is a gain that can't be had with a function that isn't nothrow. - Jonathan M Davis
Jun 10 2018
next sibling parent reply Bauss <jj_1337 live.dk> writes:
On Monday, 11 June 2018 at 00:47:27 UTC, Jonathan M Davis wrote:
 On Sunday, June 10, 2018 23:59:17 Bauss via Digitalmars-d-learn 
 wrote:
 What is the point of nothrow if it can only detect when 
 Exception is thrown and not when Error is thrown?

 It seems like the attribute is useless because you can't 
 really use it as protection to write bugless, safe code since 
 the nasty bugs will pass by just fine.

 I'm aware that it's a feature that nothrow can throw Error, 
 but it makes the attribute completely useless because you 
 basically have no safety to guard against writing code that 
 throws Error.

 To an extend  safe works, but there are tons of stuff that 
 throws Error which you can only detect and guard against 
 manually.

 So what is the point of nothrow when it can only detect 
 exceptions you'd catch anyway.

 To me it would be so much more useful if you could detect code 
 that could possibly throw Error.
Why do you care about detecting code that can throw an Error? Errors are supposed to kill the program, not get caught. As such, why does it matter if it can throw an Error? Now, personally, I'm increasingly of the opinion that the fact that we have Errors is kind of dumb given that if it's going to kill the program, and it's not safe to do clean-up at that point, because the program is in an invalid state, then why not just print the message and stack trace right there and then kill the program instead of throwing anything? But unforntunately, that's not what happens, which does put things in the weird state where code can catch an Error even though it shouldn't be doing that. As for the benefits of nothrow, as I understand it, they're twofold: 1. You know that you don't have to worry about any Exceptions being thrown from that code. You don't have to worry about doing any exception handling or having to ensure that anything gets cleaned up because of an Exception being thrown. 2. If the compiler knows that a function can't throw an Exception, then it doesn't have to insert any of the Exception handling mechanism stuff that it normally does when a function is called. It can assume that nothing ever gets thrown. If an Error does get thrown, then none of the proper clean-up will get done (e.g. constructors or scope statements), but because an Error being thrown means that the program is in an invalid state, it's not actually safe to be doing clean-up anyway. So, the fact that a function is nothrow gives you a performance benefit, because none of that extra Exception handling stuff gets inserted. How large a benefit that is in practice, I don't know, but it is a gain that can't be had with a function that isn't nothrow. - Jonathan M Davis
Well at least from my point of view I would care about code that can throw Error, because if say nothrow could detect that then you could prevent writing that code that throws jt at all and thus you'd be writing less error prone code. Maybe not necessarily nothrow, but something else that could ensure that your code is "100% safe" to run without any errors happening from ex. Accessing out of bounds, accessing invalid memory, attempting to access the member of an uninitialized class etc. Like you'd have to handle each such cases. Writing code in D today you have to think about each statement you write and whether it could possibly throw Error because you have little to no tools that helps you preventing writing such code. I'm very well aware that Error is not supposed to be caught and that the program is in an invalid state, but ehat I'm trying to get at is that if nothrow or at least a feature similar existed that could detect code that may throw Error, then you could prevent writing code that throws it in the first place. It would be a great tool to writing bugless code.
Jun 10 2018
next sibling parent Jonathan M Davis <newsgroup.d jmdavisprog.com> writes:
On Monday, June 11, 2018 04:11:38 Bauss via Digitalmars-d-learn wrote:
 I'm very well aware that Error is not supposed to be caught and
 that the program is in an invalid state, but ehat I'm trying to
 get at is that if nothrow or at least a feature similar existed
 that could detect code that may throw Error, then you could
 prevent writing code that throws it in the first place.

 It would be a great tool to writing bugless code.
Well, the problem with that is that if you do anything involving assertions, dynamic arrays, or GC memory allocations, you can get an Error. The same goes for some stuff like final switch statements. Some of those Errors don't happen with -release (e.g. the check on final switch and asserion failures), but enough operations have to be checked at runtime that I expect that even if you ignored the ones that don't happen with -release, relatively little code could be guaranteed to not throw Errors. And most Errors are thrown because of Error conditions that can't reasonably be caught at compile time. So, while knowing that none of those Errors can happen in a particular piece of code might be nice, all it really means is that you're not doing any operations in that code which can be checked for error conditions at runtime but which can't be checked at compile time. On the whole, what Errors are really doing is catching the bugs that you didn't manage to catch yourself and that the compiler can't catch for you, but the runtime can. So, arguably, all you'd really be doing if you guaranteed that a piece of code didn't throw any Errors is guarantee that the code didn't do any operations where the runtime can catch bugs for you. As such, while you obviously don't want to end up having any Errors thrown in your program, I seriously question that trying to write code that is statically guaranteed to not throw any Errors is very useful or desirable - especially since it's not like such code is guaranteed to be bug-free. It just wouldn't have any of the bugs that the runtime can catch for you. - Jonathan M Davis
Jun 10 2018
prev sibling parent Meta <jared771 gmail.com> writes:
On Monday, 11 June 2018 at 04:11:38 UTC, Bauss wrote:
 On Monday, 11 June 2018 at 00:47:27 UTC, Jonathan M Davis wrote:
 On Sunday, June 10, 2018 23:59:17 Bauss via 
 Digitalmars-d-learn wrote:
 What is the point of nothrow if it can only detect when 
 Exception is thrown and not when Error is thrown?

 It seems like the attribute is useless because you can't 
 really use it as protection to write bugless, safe code since 
 the nasty bugs will pass by just fine.

 I'm aware that it's a feature that nothrow can throw Error, 
 but it makes the attribute completely useless because you 
 basically have no safety to guard against writing code that 
 throws Error.

 To an extend  safe works, but there are tons of stuff that 
 throws Error which you can only detect and guard against 
 manually.

 So what is the point of nothrow when it can only detect 
 exceptions you'd catch anyway.

 To me it would be so much more useful if you could detect 
 code that could possibly throw Error.
Why do you care about detecting code that can throw an Error? Errors are supposed to kill the program, not get caught. As such, why does it matter if it can throw an Error? Now, personally, I'm increasingly of the opinion that the fact that we have Errors is kind of dumb given that if it's going to kill the program, and it's not safe to do clean-up at that point, because the program is in an invalid state, then why not just print the message and stack trace right there and then kill the program instead of throwing anything? But unforntunately, that's not what happens, which does put things in the weird state where code can catch an Error even though it shouldn't be doing that. As for the benefits of nothrow, as I understand it, they're twofold: 1. You know that you don't have to worry about any Exceptions being thrown from that code. You don't have to worry about doing any exception handling or having to ensure that anything gets cleaned up because of an Exception being thrown. 2. If the compiler knows that a function can't throw an Exception, then it doesn't have to insert any of the Exception handling mechanism stuff that it normally does when a function is called. It can assume that nothing ever gets thrown. If an Error does get thrown, then none of the proper clean-up will get done (e.g. constructors or scope statements), but because an Error being thrown means that the program is in an invalid state, it's not actually safe to be doing clean-up anyway. So, the fact that a function is nothrow gives you a performance benefit, because none of that extra Exception handling stuff gets inserted. How large a benefit that is in practice, I don't know, but it is a gain that can't be had with a function that isn't nothrow. - Jonathan M Davis
Well at least from my point of view I would care about code that can throw Error, because if say nothrow could detect that then you could prevent writing that code that throws jt at all and thus you'd be writing less error prone code. Maybe not necessarily nothrow, but something else that could ensure that your code is "100% safe" to run without any errors happening from ex. Accessing out of bounds, accessing invalid memory, attempting to access the member of an uninitialized class etc. Like you'd have to handle each such cases. Writing code in D today you have to think about each statement you write and whether it could possibly throw Error because you have little to no tools that helps you preventing writing such code. I'm very well aware that Error is not supposed to be caught and that the program is in an invalid state, but ehat I'm trying to get at is that if nothrow or at least a feature similar existed that could detect code that may throw Error, then you could prevent writing code that throws it in the first place. It would be a great tool to writing bugless code.
There's nothing unsafe about Error getting thrown in your code. Error makes your program more safe, because it terminates the program immediately instead of letting it do stuff like corrupt memory or crash the system. Error getting thrown denotes a logic error in your program. Some base assumption you've made is not actually true, and thus the program is in an invalid state and must exit immediately. The reason why nothrow cannot help you here is because these are logic errors that are only detectable at runtime. If it was possible to detect these types of errors at compile time, then there would be no need for Error.
Jun 11 2018
prev sibling next sibling parent reply Dave Jones <dave jones.com> writes:
On Monday, 11 June 2018 at 00:47:27 UTC, Jonathan M Davis wrote:
 On Sunday, June 10, 2018 23:59:17 Bauss via Digitalmars-d-learn 
 wrote:
 What is the point of nothrow if it can only detect when 
 Exception is thrown and not when Error is thrown?

 It seems like the attribute is useless because you can't 
 really use it as protection to write bugless, safe code since 
 the nasty bugs will pass by just fine.

 I'm aware that it's a feature that nothrow can throw Error, 
 but it makes the attribute completely useless because you 
 basically have no safety to guard against writing code that 
 throws Error.

 To an extend  safe works, but there are tons of stuff that 
 throws Error which you can only detect and guard against 
 manually.

 So what is the point of nothrow when it can only detect 
 exceptions you'd catch anyway.

 To me it would be so much more useful if you could detect code 
 that could possibly throw Error.
Why do you care about detecting code that can throw an Error? Errors are supposed to kill the program, not get caught. As such, why does it matter if it can throw an Error? Now, personally, I'm increasingly of the opinion that the fact that we have Errors is kind of dumb given that if it's going to kill the program, and it's not safe to do clean-up at that point, because the program is in an invalid state, then why not just print the message and stack trace right there and then kill the program instead of throwing anything? But unforntunately, that's not what happens, which does put things in the weird state where code can catch an Error even though it shouldn't be doing that.
It certainly threw (hardehar) me when a failed assert was terminating my program without telling me why. I don't know if it's just because it was happening in an OS callback function, but it was definitely a WTF. So the only solution I could figure is to catch throwable in the callback function, dump the message, and then PostQuitMessage(0). It just seems retarded that Throwables can still happen in a nothrow function.
Jun 11 2018
parent reply Jonathan M Davis <newsgroup.d jmdavisprog.com> writes:
On Monday, June 11, 2018 20:45:52 Dave Jones via Digitalmars-d-learn wrote:
 On Monday, 11 June 2018 at 00:47:27 UTC, Jonathan M Davis wrote:
 On Sunday, June 10, 2018 23:59:17 Bauss via Digitalmars-d-learn

 wrote:
 What is the point of nothrow if it can only detect when
 Exception is thrown and not when Error is thrown?

 It seems like the attribute is useless because you can't
 really use it as protection to write bugless, safe code since
 the nasty bugs will pass by just fine.

 I'm aware that it's a feature that nothrow can throw Error,
 but it makes the attribute completely useless because you
 basically have no safety to guard against writing code that
 throws Error.

 To an extend  safe works, but there are tons of stuff that
 throws Error which you can only detect and guard against
 manually.

 So what is the point of nothrow when it can only detect
 exceptions you'd catch anyway.

 To me it would be so much more useful if you could detect code
 that could possibly throw Error.
Why do you care about detecting code that can throw an Error? Errors are supposed to kill the program, not get caught. As such, why does it matter if it can throw an Error? Now, personally, I'm increasingly of the opinion that the fact that we have Errors is kind of dumb given that if it's going to kill the program, and it's not safe to do clean-up at that point, because the program is in an invalid state, then why not just print the message and stack trace right there and then kill the program instead of throwing anything? But unforntunately, that's not what happens, which does put things in the weird state where code can catch an Error even though it shouldn't be doing that.
It certainly threw (hardehar) me when a failed assert was terminating my program without telling me why. I don't know if it's just because it was happening in an OS callback function, but it was definitely a WTF.
Because Errors are handled as Throwables, they have to be caught to print out what went wrong. So, if you do something like give an extern(C) function to a C function via a function pointer, and it throws an Error, then you will probably have to catch it, print it, and then do whatever is appropriate at that point to shut down the program, whereas if it just killed the program at the point that the Error was thrown, then that wouldn't be a problem. So, that's a definite downside to the fact that Errors are thrown instead of just printing and killing the program. Another potentially serious downside is that if the program dies at the point of failure, then you can often get a coredump of the program state to debug it, whereas if an Error is thrown, then that doesn't happen. I think that part of what caused this situation is the fact that Walter has primarily worked on programs where you can restart them to get the same results (like a compiler). So, he's not used to having to debug a program failure where the program has been running for who knows how long, and you don't even know what the program input was. So, he has a tendency to expect you to be able to rerun the program to get the same results in order to debug it, whereas folks writing OS or server software are more likely to expect to have to capture the program state at the point of failure so that they have some hope of debugging the problem when they have no clue of how to reproduce it.
 So the only solution I could figure is to catch throwable in the
 callback function, dump the message, and then PostQuitMessage(0).
 It just seems retarded that Throwables can still happen in a
 nothrow function.
Well, it stems from the fact that Exceptions and Throwables are essentially different things but use essentially the same error-reporting mechanism. In a way, it make sense (especially in the case where you're dealing with a single thread that D controls), but I'm inclined to think that it was ultimately a mistake. - Jonathan M Davis
Jun 11 2018
parent reply Steven Schveighoffer <schveiguy yahoo.com> writes:
On 6/11/18 5:23 PM, Jonathan M Davis wrote:
 On Monday, June 11, 2018 20:45:52 Dave Jones via Digitalmars-d-learn wrote:
 So the only solution I could figure is to catch throwable in the
 callback function, dump the message, and then PostQuitMessage(0).
 It just seems retarded that Throwables can still happen in a
 nothrow function.
Well, it stems from the fact that Exceptions and Throwables are essentially different things but use essentially the same error-reporting mechanism. In a way, it make sense (especially in the case where you're dealing with a single thread that D controls), but I'm inclined to think that it was ultimately a mistake.
I agree that the fact you can catch throwables is a mistake, but at the same time, there are Errors thrown for things that shouldn't be Errors (like RangeError). This forces you to deal with them in places where it shouldn't be necessary. I predict at some point when Errors actually don't do proper cleanup, it is going to be a really difficult time for D. -Steve
Jun 12 2018
parent reply Kagamin <spam here.lot> writes:
On Tuesday, 12 June 2018 at 14:15:42 UTC, Steven Schveighoffer 
wrote:
 I predict at some point when Errors actually don't do proper 
 cleanup, it is going to be a really difficult time for D.
Looks like it already doesn't: https://run.dlang.io/is/OhDwtW
Jun 13 2018
parent Steven Schveighoffer <schveiguy yahoo.com> writes:
On 6/13/18 8:44 AM, Kagamin wrote:
 On Tuesday, 12 June 2018 at 14:15:42 UTC, Steven Schveighoffer wrote:
 I predict at some point when Errors actually don't do proper cleanup, 
 it is going to be a really difficult time for D.
Looks like it already doesn't: https://run.dlang.io/is/OhDwtW
Damn, that's interesting. And it's been that way since 2.061! So much for my shitty predictions :) BTW, Seb, I edited this to change it to Exception to see what happens, and then I wanted to re-run the original, so I closed it and re-clicked on the link, and it brought up my EDITED code. I had to clear the cookies on run.dlang.io from my browser to get it to restore. This is quite annoying, can it be fixed? -Steve
Jun 13 2018
prev sibling next sibling parent reply wjoe <none example.com> writes:
On Monday, 11 June 2018 at 00:47:27 UTC, Jonathan M Davis wrote:
 On Sunday, June 10, 2018 23:59:17 Bauss via Digitalmars-d-learn 
 wrote:
 Errors are supposed to kill the program, not get caught. As 
 such, why does it matter if it can throw an Error?

 Now, personally, I'm increasingly of the opinion that the fact 
 that we have Errors is kind of dumb given that if it's going to 
 kill the program, and it's not safe to do clean-up at that 
 point, because the program is in an invalid state, then why not 
 just print the message and stack trace right there and then 
 kill the program instead of throwing anything? But 
 unforntunately, that's not what happens, which does put things 
 in the weird state where code can catch an Error even though it 
 shouldn't be doing that.
Sorry for off topic but this means that I should revoke a private key every time a server crashes because it's not possible to erase secrets from RAM ?
Jun 12 2018
parent reply Jonathan M Davis <newsgroup.d jmdavisprog.com> writes:
On Tuesday, June 12, 2018 17:38:07 wjoe via Digitalmars-d-learn wrote:
 On Monday, 11 June 2018 at 00:47:27 UTC, Jonathan M Davis wrote:
 On Sunday, June 10, 2018 23:59:17 Bauss via Digitalmars-d-learn
 wrote:
 Errors are supposed to kill the program, not get caught. As
 such, why does it matter if it can throw an Error?

 Now, personally, I'm increasingly of the opinion that the fact
 that we have Errors is kind of dumb given that if it's going to
 kill the program, and it's not safe to do clean-up at that
 point, because the program is in an invalid state, then why not
 just print the message and stack trace right there and then
 kill the program instead of throwing anything? But
 unforntunately, that's not what happens, which does put things
 in the weird state where code can catch an Error even though it
 shouldn't be doing that.
Sorry for off topic but this means that I should revoke a private key every time a server crashes because it's not possible to erase secrets from RAM ?
The fact that an Error was thrown means that either the program ran out of a resource that it requires to do it's job and assumes is available such that it can't continue without it (e.g. failed memory allocation) and/or that the program logic is faulty. At that point, the program is in an invalid state, and by definition can't be trusted to do the right thing. Once the program is in an invalid state, running destructors, scope statements, etc. could actually make things much worse. They could easily be operating on invalid data and do entirely the wrong thing. Yes, there are cases where someone could look at what's happening and determine that based on what exactly went wrong, some amount of clean-up is safe, but without knowing exactly what went wrong and why, that's not possible. And remember that regardless of what happens with Errors, other things can kill your program (e.g. segfaults), so if you want a robust server application, you have to deal with crashes regardless. You can't rely on your program always exiting cleanly or doing any proper clean-up, much as you want it to exit cleanly normally. Either way, if your program is crashing frequently enough that the lack of clean-up poses a real problem, then you have serious problems anyway. Certainly, if you're getting enough crashes that having to do something annoying like revoke a private key is happening anything but rarely, then you have far worse problems than having to revoke a private key or whatever else you might have to do because the program didn't shut down cleanly. - Jonathan M Davis
Jun 12 2018
parent reply wjoe <none example.com> writes:
On Tuesday, 12 June 2018 at 18:41:07 UTC, Jonathan M Davis wrote:
 On Tuesday, June 12, 2018 17:38:07 wjoe via Digitalmars-d-learn 
 wrote:
 On Monday, 11 June 2018 at 00:47:27 UTC, Jonathan M Davis 
 wrote:
 On Sunday, June 10, 2018 23:59:17 Bauss via 
 Digitalmars-d-learn
 wrote:
 Errors are supposed to kill the program, not get caught. As
 such, why does it matter if it can throw an Error?

 Now, personally, I'm increasingly of the opinion that the 
 fact that we have Errors is kind of dumb given that if it's 
 going to kill the program, and it's not safe to do clean-up 
 at that point, because the program is in an invalid state, 
 then why not just print the message and stack trace right 
 there and then kill the program instead of throwing 
 anything? But unforntunately, that's not what happens, which 
 does put things in the weird state where code can catch an 
 Error even though it shouldn't be doing that.
Sorry for off topic but this means that I should revoke a private key every time a server crashes because it's not possible to erase secrets from RAM ?
The fact that an Error was thrown means that either the program ran out of a resource that it requires to do it's job and assumes is available such that it can't continue without it (e.g. failed memory allocation) and/or that the program logic is faulty. At that point, the program is in an invalid state, and by definition can't be trusted to do the right thing. Once
If memory serves a failure to malloc in C can easily be checked for success by comparing the returned pointer to null prior to accessing it. If the pointer is null this only means that memory allocation for the requested size failed. I fail to see how this attempt at malloc could have corrupted the entire program state invalid. Why would it be inherently unsafe to free memory and try to malloc again. But maybe it's an optional feature and could just be disabled. But maybe it does mean that the program cannot continue. I still don't see a need to force quit without the opportunity to decide whether it's an error to abort or an error that can be fixed during run time.
 the program is in an invalid state, running destructors, scope 
 statements, etc. could actually make things much worse. They 
 could easily be operating on invalid data and do entirely the 
 wrong thing. Yes, there are cases where someone could look at
could. Like erasing the hard drive ? But that could have happened already. Could be the reason of the error, in the first place. Destructors, scope statements etc. could also still work flawlessly and it could become worse because of not exiting gracefully. Data not synced to disk, rollback not executed, vital shutdown commands omitted.
 what's happening and determine that based on what exactly went 
 wrong, some amount of clean-up is safe, but without knowing 
 exactly what went wrong and why, that's not possible.
But Errors have names, or codes. So it should be possible to figure out what or why. No? In case of an out of memory error, maybe the error could be resolved by running the GC and retry. I'm afraid I really can't grasp the idea why it's the end of the world because an Error was thrown.
 And remember that regardless of what happens with Errors, other 
 things can kill your program (e.g. segfaults), so if you want a 
 robust server application, you have to deal with crashes 
 regardless. You can't rely on your program always exiting 
 cleanly or doing any proper clean-up, much as you want it to 
 exit cleanly normally. Either way, if your program is crashing
it is possible to install a signal handler for almost every signal on POSIX, including segfault. The only signal you can't catch is signal 9 - sigkill if memory serves. So I could for instance install a clean up handler on a segfault via memset, or a for loop, and then terminate. If program state, and not necessarily just my own programs but any programs that store secrets in RAM, is to be considered invalid on a thrown Error, and I cannot rely on proper clean up, I must consider a secret leaked as soon as it is stored in RAM at the same time an Error is thrown. Therefore the only conclusion is that such a language is not safe to use for applications that handle sensitive information, such as encrypted email, digital signing, secure IM or anything that requires secrets to perform it's work. This is really sad because I want to think that improved technology is actually better than it's precursors. What I would hope for is a mechanism to help the developer to safely handle these error conditions, or at least gracefully terminate. Now I understand that nothing can be done about program state actually messed up beyond repair and the program terminated by the OS but just assuming all is FUBAR because of throw Error is cheap.
 frequently enough that the lack of clean-up poses a real 
 problem, then you have serious problems anyway. Certainly, if 
 you're getting enough crashes that having to do something 
 annoying like revoke a private key is happening anything but 
 rarely, then you have far worse problems than having to revoke 
 a private key or whatever else you might have to do because the 
 program didn't shut down cleanly.

 - Jonathan M Davis
I can't know if the error was caused by accident or on purpose. And I don't see how frequency of failure changes anything about the fact. If a secret is left in RAM it can be read or become included in a coredump. Whether it leaked the first time or not, or not at all I wouldn't know but a defensive approach would be to assume the worst case the first time. Also it doesn't just relate to secrets not being cleaned up, but I could imagine something like sending out a udp packet or a signal on a pin or something alike to have external hardware stop its operation. Emergency stop comes to mind. Further, does it mean that a unitest should run each test case in it's own process? Because an assert(false) for a not yet implemented test case would render all further test cases (theoretically) undefined, which would make the unitest{} blocks rather useless ,too? Sorry for off topic...
Jun 12 2018
next sibling parent reply Jonathan M Davis <newsgroup.d jmdavisprog.com> writes:
On Wednesday, June 13, 2018 02:02:54 wjoe via Digitalmars-d-learn wrote:
 On Tuesday, 12 June 2018 at 18:41:07 UTC, Jonathan M Davis wrote:
 On Tuesday, June 12, 2018 17:38:07 wjoe via Digitalmars-d-learn

 wrote:
 On Monday, 11 June 2018 at 00:47:27 UTC, Jonathan M Davis

 wrote:
 On Sunday, June 10, 2018 23:59:17 Bauss via
 Digitalmars-d-learn
 wrote:
 Errors are supposed to kill the program, not get caught. As
 such, why does it matter if it can throw an Error?

 Now, personally, I'm increasingly of the opinion that the
 fact that we have Errors is kind of dumb given that if it's
 going to kill the program, and it's not safe to do clean-up
 at that point, because the program is in an invalid state,
 then why not just print the message and stack trace right
 there and then kill the program instead of throwing
 anything? But unforntunately, that's not what happens, which
 does put things in the weird state where code can catch an
 Error even though it shouldn't be doing that.
Sorry for off topic but this means that I should revoke a private key every time a server crashes because it's not possible to erase secrets from RAM ?
The fact that an Error was thrown means that either the program ran out of a resource that it requires to do it's job and assumes is available such that it can't continue without it (e.g. failed memory allocation) and/or that the program logic is faulty. At that point, the program is in an invalid state, and by definition can't be trusted to do the right thing. Once
If memory serves a failure to malloc in C can easily be checked for success by comparing the returned pointer to null prior to accessing it. If the pointer is null this only means that memory allocation for the requested size failed. I fail to see how this attempt at malloc could have corrupted the entire program state invalid. Why would it be inherently unsafe to free memory and try to malloc again. But maybe it's an optional feature and could just be disabled. But maybe it does mean that the program cannot continue. I still don't see a need to force quit without the opportunity to decide whether it's an error to abort or an error that can be fixed during run time.
Most programs do not handle the case where they run out of memory and cannot continue at that point. For better or worse, D's GC was designed with that in mind, and it treats failed allocations as an Error. In the vast majority of cases, this is desirable behavior. In those cases when it isn't, alternate memory allocation schemes such as malloc can be used. But regardless of whether the decision to treat failed memory allocations as an Error was a good one or not, the fact remains that as soon as an Error is thrown, you lose the ability to deal with things cleanly, because full clean up is not done when an Error is thrown (and can't be due to things like how nothrow works). So, regardless of whether a failed memory allocation is a condition that can be recovered from in principle, the way that D handles GC allocations make it unrecoverable in practice - at least as far as GC-allocated memory is concerned.
 the program is in an invalid state, running destructors, scope
 statements, etc. could actually make things much worse. They
 could easily be operating on invalid data and do entirely the
 wrong thing. Yes, there are cases where someone could look at
could. Like erasing the hard drive ? But that could have happened already. Could be the reason of the error, in the first place. Destructors, scope statements etc. could also still work flawlessly and it could become worse because of not exiting gracefully. Data not synced to disk, rollback not executed, vital shutdown commands omitted.
The point is that once the program is in an invalid state, you have no way of knowing whether attempting to do anything else in the program (including running clean up code) is going to make matters better or worse. And since robust programs must be able to deal with crashes anyway, in general, it makes far more sense to forgo any clean up and avoid the risk of doing further damage. Whatever mechanisms are used to deal with a crashed program can then be used just like if the program crashed for any other reason.
 what's happening and determine that based on what exactly went
 wrong, some amount of clean-up is safe, but without knowing
 exactly what went wrong and why, that's not possible.
But Errors have names, or codes. So it should be possible to figure out what or why. No? In case of an out of memory error, maybe the error could be resolved by running the GC and retry. I'm afraid I really can't grasp the idea why it's the end of the world because an Error was thrown.
Errors are specifically for non-recoverable conditions where it is not considered desirable or reasonable to continue the program - be it because of a bug in the program's logic, a lack of a resource that the program needs and cannot function without, or any other condition where the program is in an invalid state. If the condition is intended to be recoverable, then an Exception is used, not an Error. And of course, because the program is considered in an invalid state when an Error is thrown (and thus clean up code is skipped), attempting to recover means attempting to continue the program when it's in an invalid state, which could easily do more harm than good. The entire distinction between Exception and Error has to do with whether the condition is considered to be something that could be recovered from or not. You can debate whether a particular condition should be treated as an Exception or Error, but the distinction between the two in terms of how they should be handled is quite clear. It's perfectly reasonable, acceptable, and desirable to catch Exceptions in order to handle the error condition and recover. It is not reasonable to attempt to catch Errors and attempt to recover. The simple fact that it is an Error makes it that way regardless of whether that particular condition should or should not have been treated as an Error in the first place.
 And remember that regardless of what happens with Errors, other
 things can kill your program (e.g. segfaults), so if you want a
 robust server application, you have to deal with crashes
 regardless. You can't rely on your program always exiting
 cleanly or doing any proper clean-up, much as you want it to
 exit cleanly normally. Either way, if your program is crashing
it is possible to install a signal handler for almost every signal on POSIX, including segfault. The only signal you can't catch is signal 9 - sigkill if memory serves. So I could for instance install a clean up handler on a segfault via memset, or a for loop, and then terminate. If program state, and not necessarily just my own programs but any programs that store secrets in RAM, is to be considered invalid on a thrown Error, and I cannot rely on proper clean up, I must consider a secret leaked as soon as it is stored in RAM at the same time an Error is thrown. Therefore the only conclusion is that such a language is not safe to use for applications that handle sensitive information, such as encrypted email, digital signing, secure IM or anything that requires secrets to perform it's work. This is really sad because I want to think that improved technology is actually better than it's precursors. What I would hope for is a mechanism to help the developer to safely handle these error conditions, or at least gracefully terminate. Now I understand that nothing can be done about program state actually messed up beyond repair and the program terminated by the OS but just assuming all is FUBAR because of throw Error is cheap.
Errors are specifically cases where it's not considered reasonable to handle the error condition. The whole point is that they can't be handled safely, and the best course of action is to kill the program without attempting any clean-up. But remember that Errors are supposed to be rare. If they're happening often enough to cause real problems in prouction code, then you have much bigger problems than whether the program is attempting clean-up on shutdown or not. Also, because the fact that an Error is thrown means that the program is in an invalid state, even if it _did_ attempt clean-up, it would be a terrible idea to assume that that clean-up worked properly. So, any program that truly needs to do clean-up after an Error is thrown is really going to need to do something like do clean-up when the program restarts. And yes, there are potential problems there, but that's what happens when your program gets into an invalid state and is one of the reasons why you want to throughly test software before putting it into production. And the reality of the matter is that you can't rely on clean-up in _any_ language. There is always a way to kill a program without it being able to do full clean-up, even if that means simply pulling the plug on the computer. Pulling the plug may not affect concerns about leaving data in memory, but you yourself just said that sigkill can't be handled. So, you have a way right there that you can't rely on clean-up happening - and it's not like it's hard to kill a program as long as your user has the permsissions to do so. So, any program that really needs to care about clean-up is going to need a way to handle cases like that.
 frequently enough that the lack of clean-up poses a real
 problem, then you have serious problems anyway. Certainly, if
 you're getting enough crashes that having to do something
 annoying like revoke a private key is happening anything but
 rarely, then you have far worse problems than having to revoke
 a private key or whatever else you might have to do because the
 program didn't shut down cleanly.

 - Jonathan M Davis
I can't know if the error was caused by accident or on purpose. And I don't see how frequency of failure changes anything about the fact. If a secret is left in RAM it can be read or become included in a coredump. Whether it leaked the first time or not, or not at all I wouldn't know but a defensive approach would be to assume the worst case the first time. Also it doesn't just relate to secrets not being cleaned up, but I could imagine something like sending out a udp packet or a signal on a pin or something alike to have external hardware stop its operation. Emergency stop comes to mind. Further, does it mean that a unitest should run each test case in it's own process? Because an assert(false) for a not yet implemented test case would render all further test cases (theoretically) undefined, which would make the unitest{} blocks rather useless ,too? Sorry for off topic...
I would not advise calling functions in unittest blocks that just assert false. If they're called directly, it doesn't matter much, since clean-up is done for AssertErrors in unittest blocks, but if it's deeper in the call stack, then you could get into an invalid state. How much that matters depends on how independent your tests are, but it would be better to avoid it. However, even if things do get into a screwed up state, this is a unittest run that we're talking about here. It's not in production and therefore presumably can't do real damage. All of those test failures should be fixed long before the code hits production, so any screwyness shouldn't cause long term problems. But still, in general, you really don't want to be trusting what happens with a unittest build after an assertion failure occurs outside of a unittest block. It might be valid, or it might not. - Jonathan M Davis
Jun 12 2018
parent reply wjoe <none example.com> writes:
On Wednesday, 13 June 2018 at 03:14:33 UTC, Jonathan M Davis 
wrote:
 Most programs do not handle the case where they run out of 
 memory and cannot continue at that point. For better or worse, 
 D's GC was designed with that in mind, and it treats failed 
 allocations as an Error. In the vast majority of cases, this is 
 desirable behavior. In those cases when it isn't, alternate 
 memory allocation schemes such as malloc can be used. But
But manual memory management sucks and is a huge waste of everyone's time and I was hoping to get the best from both worlds :)
 regardless of whether the decision to treat failed memory 
 allocations as an Error was a good one or not, the fact remains 
 that as soon as an Error is thrown, you lose the ability to 
 deal with things cleanly, because full clean up is not done 
 when an Error is thrown (and can't be due to things like how 
 nothrow works). So, regardless of whether a failed memory 
 allocation is a condition that can be recovered from in 
 principle, the way that D handles GC allocations make it 
 unrecoverable in practice - at least as far as GC-allocated 
 memory is concerned.
Did I get that right? You say when an error is thrown destructors, scope statements, etc. are not executed - if declared as nothrow because the exception handler mechanism stuff is missing, is that correct? And it does execute if not declared as nothrow but can't be relied upon because some other nothrow functions could have omitted some of those statements? So I shoot myself in the foot with nothrow and if I don't use it I'm still in a world of hurt? I understand the idea that an Error is not supposed to be caught but why would such a 'feature' be desirable? Where's the benefit if nothing can be relied upon ? If all errors would be treated like an exception, the developer could decide whether it is an error which needs to terminate right away or be able to handle the issue and continue or gracefully shutdown. Could even set a break point or force a core dump right there. If the exception would be ignored the program will crash regardless but at least there would be a stack trace that I could rely upon instead of this unreliable and possibly corrupt state which is good for nothing. This concept is a bit like color everyone with the same brush or one shoe fits all. Where in reality it depends on the circumstances whether it is an error or an exception. But maybe I feel that way because currently there's a bit of a blur regarding what's defined as Errors and Exceptions. Anyways I took a lot from your awesome explanations so far. Thanks a ton!
Jun 13 2018
next sibling parent reply Kagamin <spam here.lot> writes:
On Wednesday, 13 June 2018 at 10:56:41 UTC, wjoe wrote:
 I understand the idea that an Error is not supposed to be 
 caught but why would such a 'feature' be desirable? Where's the 
 benefit if nothing can be relied upon ?
It's a debugging facility for development stage that allows to print the error message and stack trace instead of silent termination. Because it still needs to be caught for this, explicit catch still works, but other cleanup mechanisms don't.
Jun 13 2018
parent reply wjoe <none example.com> writes:
On Wednesday, 13 June 2018 at 13:05:44 UTC, Kagamin wrote:
 On Wednesday, 13 June 2018 at 10:56:41 UTC, wjoe wrote:
 I understand the idea that an Error is not supposed to be 
 caught but why would such a 'feature' be desirable? Where's 
 the benefit if nothing can be relied upon ?
It's a debugging facility for development stage that allows to print the error message and stack trace instead of silent termination. Because it still needs to be caught for this, explicit catch still works, but other cleanup mechanisms don't.
My question was more like what's the benefit of having thrown Errors corrupt your program state rendering it useless for debugging ?
Jun 13 2018
parent reply Kagamin <spam here.lot> writes:
On Wednesday, 13 June 2018 at 17:08:26 UTC, wjoe wrote:
 My question was more like what's the benefit of having thrown 
 Errors corrupt your program state  rendering it useless for 
 debugging ?
D allows various levels of performance and safety. Though I'd say Errors not working in debug mode is not intended, the optimization should work in release mode which implies debugged code and assumes there are no Errors thrown and you get extra optimization for nothrow functions. Errors are a cheap way to print diagnostic, because you need to do it for unhandled exceptions anyway and it's cross-platform too unlike debugger. Also leaf functions don't know anything about environment and can't do meaningful I/O, e.g. realistically you have standard output only in console applications and not in other applications.
Jun 15 2018
parent reply wjoe <none example.com> writes:
On Friday, 15 June 2018 at 08:13:44 UTC, Kagamin wrote:
 On Wednesday, 13 June 2018 at 17:08:26 UTC, wjoe wrote:
 My question was more like what's the benefit of having thrown 
 Errors corrupt your program state  rendering it useless for 
 debugging ?
D allows various levels of performance and safety. Though I'd say Errors not working in debug mode is not intended, the
Intention matters not. By definition all program state is invalid at the point an Error was thrown. From there on it is impossible to rely on any output, too, because it could be either correct, corrupted, or completely invalid. Your objects might have been destructed, or maybe not or maybe just partially. The only thing safe to assume is that what you've got is useless.
 optimization should work in release mode which implies debugged 
 code and assumes there are no Errors thrown and you get extra 
 optimization for nothrow functions. Errors are a cheap way to 
 print diagnostic, because you need to do it for unhandled 
 exceptions anyway and it's cross-platform too unlike debugger.
A core dump is created by the OS. In a format that a native debugger understands.
 Also leaf functions don't know anything about environment and 
 can't do meaningful I/O, e.g. realistically you have standard 
 output only in console applications and not in other 
 applications.
Exactly. You may not have a console at all, like eg. in Windows for the most part, or even Linux if you launch the program from a toolbar button, and what about headless configurations. What good is printing to stderr in these cases ? The only sensible thing to do in case of an unrecoverable Error is to transfer control back to the OS right away and let it handle the rest. A mechanism of Errors thrown like Exceptions is too tempting to mess around with. Scott Meyers wrote in one of his books, I forget which, that your design should be easy to use correctly and hard or impossible to use incorrectly. This is not true for D Errors.
Jun 15 2018
parent reply Kagamin <spam here.lot> writes:
On Friday, 15 June 2018 at 17:46:02 UTC, wjoe wrote:
 D allows various levels of performance and safety. Though I'd 
 say Errors not working in debug mode is not intended, the
Intention matters not. By definition all program state is invalid at the point an Error was thrown. From there on it is impossible to rely on any output, too, because it could be either correct, corrupted, or completely invalid.
The program is in invalid state when it hits a bug before Error is thrown, this is seen as a property of a buggy algorithm, Error is thrown only as a diagnostic of a bug that has happened already. The state is invalid in a sense that the program shouldn't continue to serve its intended purpose. Even if Error was technically correctly unwound, it won't necessarily provide a correct cleanup when algorithm doesn't expect an exception. Though in case of D situation may be not as clear as there is safe code, but we just recently had a nasty memory corruption bug caused by incorrect trusted code.
 A core dump is created by the OS. In a format that a native 
 debugger understands.
Most of the time a stack trace is enough to diagnose the error and provides a better UX than a core dump (especially to newbies). I saw gdb crash trying to make sense of a debugged program too. Runtime allows to override failure handlers, but it's not centralized.
Jun 19 2018
parent reply wjoe <none example.com> writes:
On Tuesday, 19 June 2018 at 12:26:15 UTC, Kagamin wrote:
 On Friday, 15 June 2018 at 17:46:02 UTC, wjoe wrote:
 D allows various levels of performance and safety. Though I'd 
 say Errors not working in debug mode is not intended, the
Intention matters not. By definition all program state is invalid at the point an Error was thrown. From there on it is impossible to rely on any output, too, because it could be either correct, corrupted, or completely invalid.
The program is in invalid state when it hits a bug before Error is thrown, this is seen as a property of a buggy algorithm, Error is thrown only as a diagnostic of a bug that has happened already. The state is invalid in a sense that the program shouldn't continue to serve its intended purpose. Even if Error was technically correctly unwound, it won't necessarily provide a correct cleanup when algorithm doesn't expect an exception. Though in case of D situation may be not as clear as there is safe code, but we just recently had a nasty memory corruption bug caused by incorrect trusted code.
I wrote that 4 days ago. I lost some sleep over that matter and am long past the idea of trying to correctly clean up in this situation. You would know that had you read my more recent posts.
 A core dump is created by the OS. In a format that a native 
 debugger understands.
Most of the time a stack trace is enough to diagnose the error
I'll say it again. The program must have a console(like) device attached. Otherwise you will not have a stack trace - or at least it needs to be redirected to a file but that's not very newbie friendly either because each shell has their own way of doing it and csh, for example, can't even redirect individually. I'm not sure about Windows. Even if possible, considering the heavy focus on GUI, I doubt it's considered best practices there and is a PITA for sure. But maybe I missed something else and the only purpose of D is to make console applications for *NIX like OSs and expect users to be professional enough to save that stack trace before they close the terminal ? And how can you be sure that this bug didn't corrupt memory of the druntime or anything else related to the stack trace, or even that it is a single bug ? And how useful is a stack trace that shows a back trace to the point of the location the Error was thrown compared to a back trace to the location of the bug (report)?
 and provides a better UX than a core dump (especially to
Please explain. A core dump has everything a printed stack trace has and more and is as easy as using the debugger itself.
 newbies). I saw gdb crash trying to make sense of a debugged 
 program too. Runtime allows to override failure handlers, but 
 it's not centralized.
And what guarantee is there that the runtime doesn't crash trying to print a stack trace ? Could happen just as likely.
Jun 19 2018
parent reply Kagamin <spam here.lot> writes:
On Tuesday, 19 June 2018 at 15:03:49 UTC, wjoe wrote:
 But maybe I missed something else and the only purpose of D is 
 to make console applications for *NIX like OSs and expect users 
 to be professional enough to save that stack trace before they 
 close the terminal ?
I just read stack trace from console. Initially D ecosystem focused on windows console applications, linux support came later, and compiling windows gui application is not straightforward. Simply because console support is the first thing to implement.
 And how can you be sure that this bug didn't corrupt memory of 
 the druntime or anything else related to the stack trace, or 
 even that it is a single bug ?
The state is invalid in a sense that program shouldn't continue to serve its intended purpose.
 And how useful is a stack trace that shows a back trace to the 
 point of the location the Error was thrown compared to a back 
 trace to the location of the bug (report)?
In most cases stack trace is enough to diagnose the error.
 and provides a better UX than a core dump (especially to
Please explain. A core dump has everything a printed stack trace has and more and is as easy as using the debugger itself.
Do you know how to extract information from it on an unfamiliar OS? Reading stack trace is easier and self-evident.
Jun 20 2018
parent reply wjoe <none example.com> writes:
On Wednesday, 20 June 2018 at 12:22:33 UTC, Kagamin wrote:
 On Tuesday, 19 June 2018 at 15:03:49 UTC, wjoe wrote:
 But maybe I missed something else and the only purpose of D is 
 to make console applications for *NIX like OSs and expect 
 users to be professional enough to save that stack trace 
 before they close the terminal ?
I just read stack trace from console. Initially D ecosystem focused on windows console applications, linux support came later, and compiling windows gui application is not straightforward. Simply because console support is the first thing to implement.
 And how can you be sure that this bug didn't corrupt memory of 
 the druntime or anything else related to the stack trace, or 
 even that it is a single bug ?
The state is invalid in a sense that program shouldn't continue to serve its intended purpose.
Either it is invalid, or if it is safe for the druntime to assume that it's safe to do whatever it does, then it's just as safe to assume that an installed signal handler called by the OS is doing it's thing just fine as well, like stopping a motor.
 And how useful is a stack trace that shows a back trace to the 
 point of the location the Error was thrown compared to a back 
 trace to the location of the bug (report)?
In most cases stack trace is enough to diagnose the error.
In most cases errors are easy to fix, too. I worry about the corner cases. The really annoying bugs. The bugs you might only get one shot at because you don't know how to reproduce, which you can only diagnose and fix via post mortem debugging.
 and provides a better UX than a core dump (especially to
Please explain. A core dump has everything a printed stack trace has and more and is as easy as using the debugger itself.
Do you know how to extract information from it on an unfamiliar OS? Reading stack trace is easier and self-evident.
Counter question: How do you develop for an unfamiliar OS with unfamiliar tools in the first place ? The concept of a debugger and a memory dump is fundamentally the same on every OS I know or care about just as much as the D error implementation doesn't care about niche cases. Of course you can debug your applications via print to console if you feel that this is productive enough and ignore the bugs you can't fix that way.
Jun 21 2018
parent reply Jonathan M Davis <newsgroup.d jmdavisprog.com> writes:
On Thursday, June 21, 2018 13:16:28 wjoe via Digitalmars-d-learn wrote:
 On Wednesday, 20 June 2018 at 12:22:33 UTC, Kagamin wrote:
 Do you know how to extract information from it on an unfamiliar
 OS? Reading stack trace is easier and self-evident.
Counter question: How do you develop for an unfamiliar OS with unfamiliar tools in the first place ? The concept of a debugger and a memory dump is fundamentally the same on every OS I know or care about just as much as the D error implementation doesn't care about niche cases. Of course you can debug your applications via print to console if you feel that this is productive enough and ignore the bugs you can't fix that way.
Simply having a stack trace would be plenty in many cases, and if you're primarily developing an a different OS from the one the user was on when the error occurred, getting a stack trace may allow you to see what the problem is and fix it without setting up a debugger on the OS that the user was running (which could be a huge timesaver if you don't normally use that OS). That being said, the optimal solution is likely printing out the error message and stack trace, and then giving a coredump (or the OS' equivalent) at the point of the failure. Then if the message and stack trace are enough, you're good to go, and if you need the coredump to get more detailed information, then you have it. - Jonathan M Davis
Jun 21 2018
parent wjoe <none example.com> writes:
On Thursday, 21 June 2018 at 19:52:25 UTC, Jonathan M Davis wrote:
 On Thursday, June 21, 2018 13:16:28 wjoe via 
 Digitalmars-d-learn wrote:
 On Wednesday, 20 June 2018 at 12:22:33 UTC, Kagamin wrote:
 Do you know how to extract information from it on an 
 unfamiliar OS? Reading stack trace is easier and 
 self-evident.
Counter question: How do you develop for an unfamiliar OS with unfamiliar tools in the first place ? The concept of a debugger and a memory dump is fundamentally the same on every OS I know or care about just as much as the D error implementation doesn't care about niche cases. Of course you can debug your applications via print to console if you feel that this is productive enough and ignore the bugs you can't fix that way.
Simply having a stack trace would be plenty in many cases, and if you're primarily developing an a different OS from the one the user was on when the error occurred, getting a stack trace may allow you to see what the problem is and fix it without setting up a debugger on the OS that the user was running (which could be a huge timesaver if you don't normally use that
That is if that other OS provides the means to print one and the user is skilled enough to relay that info to the developer. There's apparently no other option. Because as I learned here that installing your own crash handler, for instance, which writes this stack trace to a file and submits a crash report to the developer, is not possible. Additionally, you might end up empty handed in case of a daemon since best practice in this domain is to close stdin/out/err to prevent them to litter the terminal with output and/or they may be runnig headless and this kind of output would never be seen.
 OS). That being said, the optimal solution is likely printing 
 out the error message and stack trace, and then giving a 
 coredump (or the OS' equivalent) at the point of the failure. 
 Then if the message and stack trace are enough, you're good to 
 go, and if you need the coredump to get more detailed 
 information, then you have it.

 - Jonathan M Davis
Those who are comfy rarely see the needs of others. My attempt in this regard was to show how it feels like not to have that info.
Jun 23 2018
prev sibling parent reply Jonathan M Davis <newsgroup.d jmdavisprog.com> writes:
On Wednesday, June 13, 2018 10:56:41 wjoe via Digitalmars-d-learn wrote:
 On Wednesday, 13 June 2018 at 03:14:33 UTC, Jonathan M Davis

 wrote:
 Most programs do not handle the case where they run out of
 memory and cannot continue at that point. For better or worse,
 D's GC was designed with that in mind, and it treats failed
 allocations as an Error. In the vast majority of cases, this is
 desirable behavior. In those cases when it isn't, alternate
 memory allocation schemes such as malloc can be used. But
But manual memory management sucks and is a huge waste of everyone's time and I was hoping to get the best from both worlds :) :
Well, I think that the reality of the matter is that the number of programs that even attempt to recover from not having enough memory is extremely small such that you're dealing with a very niche case if you're going to try it, and if the GC fails to allocate more memory for you, your options are typically pretty limited. So, even if the GC provided a way to allocate memory that returned null on failure instead of throwing an Error, I don't know that it would do you a lot of good, but regardless, the GC was not designed with that in mind, and even GC.malloc throws OutOfMemoryError on allocation failure rather than null. So, there isn't much choice on the matter.
 regardless of whether the decision to treat failed memory
 allocations as an Error was a good one or not, the fact remains
 that as soon as an Error is thrown, you lose the ability to
 deal with things cleanly, because full clean up is not done
 when an Error is thrown (and can't be due to things like how
 nothrow works). So, regardless of whether a failed memory
 allocation is a condition that can be recovered from in
 principle, the way that D handles GC allocations make it
 unrecoverable in practice - at least as far as GC-allocated
 memory is concerned.
Did I get that right? You say when an error is thrown destructors, scope statements, etc. are not executed - if declared as nothrow because the exception handler mechanism stuff is missing, is that correct? And it does execute if not declared as nothrow but can't be relied upon because some other nothrow functions could have omitted some of those statements?
Yes, and there's no guarantee that clean-up will occur even if nothing is nothrow. While the current implementation will do clean-up in those cases, it didn't used to, and Walter has repeatedly stated that it is not guaranteed to do so. Errors are _not_ intended to be caught and recovered from. They're essentially a segfault that prints a message and stack trace but which for some reason uses the exception throwing mechanism to get to the code that prints the message and exits the program.
 So I shoot myself in the foot with nothrow and if I don't use it
 I'm still in a world of hurt?

 I understand the idea that an Error is not supposed to be caught
 but why would such a 'feature' be desirable? Where's the benefit
 if nothing can be relied upon ?

 If all errors would be treated like an exception, the developer
 could decide whether it is an error which needs to terminate
 right away or be able to handle the issue and continue or
 gracefully shutdown.
The idea is that because your program is in an invalid state, attempting a graceful shutdown is unsafe. But regardless of whether you agree with that, the fact that nothrow doesn't do clean-up pretty much ensures that it isn't safe in the general case, and nothrow can't do clean-up without negating one of the main reasons that it exists in the first place - which is to improve performance by not emitting exception-handling code.
 Could even set a break point or force a core
 dump right there.
The fact that Errors don't immediately kill the program and instead sort of unwind the stack is a definite problem for getting good debug information on crashes. I suspect that Walter doesn't quite understand the issues here, because whenever anyone raises issues related to stuff like this, he has a tendancy to basically tell people to rerun their program - which works fantastically in the world he typically programs in (compilers) but doesn't work very well with stuff like OSes or server programs where you frequently have no clue how to replicate the problem. My guess is that Errors work they do in part because he's not used to debugging situations where a coredump being created at the point of failure the first time it happens (rather than during attempts to reproduce the problem) is what you really need. I think that the reasons that this is not a bigger problem than it is stem primarily from the fact that Errors are going to be very rare in production code unless it wasn't properly tested. So, the problem shouldn't pop up often. However, when it does, having a coredump at the site of the failure would definitely be valuable.
 If the exception would be ignored the program will crash
 regardless but at least there would be a stack trace that I could
 rely upon instead of this unreliable and possibly corrupt state
 which is good for nothing.

 This concept is a bit like color everyone with the same brush or
 one shoe fits all. Where in reality it depends on the
 circumstances whether it is an error or an exception.
 But maybe I feel that way because currently there's a bit of a
 blur regarding what's defined as Errors and Exceptions.

 Anyways I took a lot from your awesome explanations so far.
 Thanks a ton!
Personally, I'm increasingly of the opinion that having Errors was a mistake and that the better solution would have been to just print out the error message and stack trace right there and immediately kill the program. That would then give you a coredump exactly where you were and avoid all of the confusion about Errors being thrown but not really doing proper clean-up. I don't know why Walter decided to do it the way he did, particularly since he's made it very clear that the entire point of Errors is to indicate a fatal error in the program, that doing any clean-up at that point is dangerous, and that the program needs to terminate, not try to recover. But I don't think that changing it so that Errors terminated immediately (and thus gave you a coredump for that spot in the program) would change what's an Error and what's an Exception. Either way, Errors are for error conditions that are deemed to be unrecoverable. So, it wouldn't change the fact that trying to recover from an Error is a terrible idea. It would just make it so that Errors which occurred in programs would then be more debuggable - especially in the rare cases that they happen in production. - Jonathan M Davis
Jun 13 2018
parent reply wjoe <none example.com> writes:
On Wednesday, 13 June 2018 at 20:08:06 UTC, Jonathan M Davis 
wrote:
 On Wednesday, June 13, 2018 10:56:41 wjoe via 
 Digitalmars-d-learn wrote:
 On Wednesday, 13 June 2018 at 03:14:33 UTC, Jonathan M Davis
 regardless of whether the decision to treat failed memory 
 allocations as an Error was a good one or not, the fact 
 remains that as soon as an Error is thrown, you lose the 
 ability to deal with things cleanly, because full clean up 
 is not done when an Error is thrown (and can't be due to 
 things like how nothrow works). So, regardless of whether a 
 failed memory allocation is a condition that can be 
 recovered from in principle, the way that D handles GC 
 allocations make it unrecoverable in practice - at least as 
 far as GC-allocated memory is concerned.
Did I get that right? You say when an error is thrown destructors, scope statements, etc. are not executed - if declared as nothrow because the exception handler mechanism stuff is missing, is that correct? And it does execute if not declared as nothrow but can't be relied upon because some other nothrow functions could have omitted some of those statements?
Yes, and there's no guarantee that clean-up will occur even if nothing is nothrow. While the current implementation will do
Good to know. The thought crossed my mind to remove nothrow from all functions... ;)
 clean-up in those cases, it didn't used to, and Walter has 
 repeatedly stated that it is not guaranteed to do so. Errors 
 are _not_ intended to be caught and recovered from. They're 
 essentially a segfault that prints a message and stack trace 
 but which for some reason uses the exception throwing mechanism 
 to get to the code that prints the message and exits the 
 program.
So the program is in a stable enough state to run the exception handling mechanism to print a message and die, but not stable enough to run a memset or writePin(11,0) before continuing trampling forward to where the printing and dying happens ?
 So I shoot myself in the foot with nothrow and if I don't use 
 it I'm still in a world of hurt?

 I understand the idea that an Error is not supposed to be 
 caught but why would such a 'feature' be desirable? Where's 
 the benefit if nothing can be relied upon ?

 If all errors would be treated like an exception, the 
 developer could decide whether it is an error which needs to 
 terminate right away or be able to handle the issue and 
 continue or gracefully shutdown.
The idea is that because your program is in an invalid state, attempting a graceful shutdown is unsafe. But regardless of whether you agree with that, the fact that nothrow doesn't do clean-up pretty much ensures that it isn't safe in the general case, and nothrow can't do clean-up without negating one of the main reasons that it exists in the first place - which is to
that fact also means that a program which threw an Error cannot be debugged anymore; because of invalid state you can neither know, nor assume, that what you see in your debugger or core dump is actually the state which led to the throw.
 improve performance by not emitting exception-handling code.
if performance matters so much I would use betterC. 'Improving' performance without profiling and such a trade-off is a bad idea. If it were opt in - yes, I know I will get undebuggable code on error thrown but I want or need the performance gain, fair enough. But instead you are a victim of that implementation whether you like it or not and you might not even be aware about it.
 Could even set a break point or force a core
 dump right there.
The fact that Errors don't immediately kill the program and instead sort of unwind the stack is a definite problem for getting good debug information on crashes. I suspect that Walter doesn't quite understand the issues here, because whenever anyone raises issues related to stuff like this, he has a tendancy to basically tell people to rerun their program - which works fantastically in the world he typically programs in (compilers) but doesn't work very well with stuff like OSes or server programs where you frequently have no clue how to replicate the problem. My guess is that Errors work they do in part because he's not used to debugging situations where a coredump being created at the point of failure the first time it happens (rather than during attempts to reproduce the problem) is what you really need.
Or any program which is interactive or where input is non deterministic. Out of curiosity, in case of out of memory, will the program crash trying to throw OutOfMemoryError or is it pre-allocated along with the memory needed to format and print the message? And out of curiosity again, where would I find this place where the printing and terminating occurs ?
 I think that the reasons that this is not a bigger problem than 
 it is stem primarily from the fact that Errors are going to be 
 very rare in production code unless it wasn't properly tested. 
 So, the problem shouldn't pop up often. However, when it does, 
 having a coredump at the site of the failure would definitely 
 be valuable.
It's not possible to catch every bug before shipping. And there's plenty of critical one in software of every developer. And because software was thoroughly tested before shipping, the remaining bugs are tricky to catch and are most likely not easy to reproduce. So a core dump might be all you've got and if that shows invalid state of the program, did a few things here but not there..I wouldn't want to be the sorry sod having to fix that bug. On the other hand one could just wave it off, because why bother, happens too rarely, or blame the user of doing something wrong. That works, too.
 Personally, I'm increasingly of the opinion that having Errors 
 was a mistake and that the better solution would have been to 
 just print out the error message and stack trace right there 
 and immediately kill the program. That would then give you a 
 coredump exactly where you were and avoid all of the confusion 
 about Errors being thrown but not really doing proper clean-up. 
 I don't know why Walter decided to do it the way he did, 
 particularly since he's made it very clear that the entire 
 point of Errors is to indicate a fatal error in the program, 
 that doing any clean-up at that point is dangerous, and that 
 the program needs to terminate, not try to recover.
Aborting with an error code would be sufficient. No need to print anything. A backtrace can be obtained in the debugger.
 But I don't think that changing it so that Errors terminated 
 immediately (and thus gave you a coredump for that spot in the 
 program) would change what's an Error and what's an Exception.
No it wouldn't but not everything declared or treated as an error in D is one. There should be only a few and everything else should be an Exception.
Jun 14 2018
parent reply Jonathan M Davis <newsgroup.d jmdavisprog.com> writes:
On Thursday, June 14, 2018 18:11:20 wjoe via Digitalmars-d-learn wrote:
 On Wednesday, 13 June 2018 at 20:08:06 UTC, Jonathan M Davis
 wrote:
 On Wednesday, June 13, 2018 10:56:41 wjoe via
 The idea is that because your program is in an invalid state,
 attempting a graceful shutdown is unsafe. But regardless of
 whether you agree with that, the fact that nothrow doesn't do
 clean-up pretty much ensures that it isn't safe in the general
 case, and nothrow can't do clean-up without negating one of the
 main reasons that it exists in the first place - which is to
that fact also means that a program which threw an Error cannot be debugged anymore; because of invalid state you can neither know, nor assume, that what you see in your debugger or core dump is actually the state which led to the throw.
As I said, personally, I think that the program shut just print and terminate rather than throwing an Error. Walter seems to have designed things from the premise that you could rerun the program to reproduce the problem (which in is usually true with the programs he works on). And in that case, simply getting the error message and stacktrace would be plenty. The problem is when you can't simply rerun the program to reproduce the problem and is why I'm of the opinion that printing and terminating would be better than throwing an Error.
 improve performance by not emitting exception-handling code.
if performance matters so much I would use betterC. 'Improving' performance without profiling and such a trade-off is a bad idea. If it were opt in - yes, I know I will get undebuggable code on error thrown but I want or need the performance gain, fair enough. But instead you are a victim of that implementation whether you like it or not and you might not even be aware about it.
betterC really has nothing to do with performance. It just has to do with avoiding druntime so that you can have C code just link in and use the D code as if it were C (though using it would avoid the issue of Errors, since the runtime wouldn't be there to handle them). And again, Errors are intended for fatal cases, so most of the concerns about doing clean-up are irrelevant. Attempting to recover from an Error is considered to be like attempting to recover from a segfault, which is a terrible, terrible idea. And there are plenty of folks who want to be able to have their code be more performant when it's not using exceptions. So, as long as folks aren't trying to catch Errors, the fact that nothrow doesn't emit the exception handling code really isn't a problem.
 Out of curiosity, in case of out of memory, will the program
 crash trying to throw OutOfMemoryError or is it pre-allocated
 along with the memory needed to format and print the message?
OutOfMemoryError is pre-allocated. core.exception's onOutOfMemoryError is called rather than allocating a new OutOfMemoryError.
 And out of curiosity again, where would I find this place where
 the printing and terminating occurs ?
I'd have to go digging in druntime. I don't know. I've probably seen it before, but it's not code that I've dealt with often enough to remember exactly where it is off the top of my head.
 Personally, I'm increasingly of the opinion that having Errors
 was a mistake and that the better solution would have been to
 just print out the error message and stack trace right there
 and immediately kill the program. That would then give you a
 coredump exactly where you were and avoid all of the confusion
 about Errors being thrown but not really doing proper clean-up.
 I don't know why Walter decided to do it the way he did,
 particularly since he's made it very clear that the entire
 point of Errors is to indicate a fatal error in the program,
 that doing any clean-up at that point is dangerous, and that
 the program needs to terminate, not try to recover.
Aborting with an error code would be sufficient. No need to print anything. A backtrace can be obtained in the debugger.
Given that a coredump isn't always generated (and in the case of Windows, I don't know if they even have an equivalent), printing out the same information that gets printed out now would often be desirable. It's just that if it kills the program right there rather than doing any unwinding of the stack, then the coredump is for the state of the program at the point of failure like it arguably should be.
 But I don't think that changing it so that Errors terminated
 immediately (and thus gave you a coredump for that spot in the
 program) would change what's an Error and what's an Exception.
No it wouldn't but not everything declared or treated as an error in D is one. There should be only a few and everything else should be an Exception.
There are no Errors in druntime or Phobos that I'm aware of where I would not consider it perfectly reasonable that they're Errors, but there are cases where it's certainly subjective. At some point, it comes down to a design decision - e.g. is providing an incorrect index considered a bug or simply bad input? The choice that Walter went with was that it is a bug, and that works extremely well overall, but an argument could be made the other way. It's the same with using contract programming versus defensive programming. It's a design decision, and not everyone is always going to agree about design decisions. It's also not necessarily the case that one way is right and the other is wrong. Sometimes, it's simply a matter of tradeoffs. If you don't agree with some of the design decisions, then you will generally either have to figure out how to work around them for what you want or just learn to live with them. The same goes for all of us. In some cases, a DIP could be written and accepted to change the language, but if your concerns have to do with nothrow not doing clean-up or anything like that, then I can guarantee that you're wasting your time. There _might_ be a chance of convincing Walter that the program should be terminated at the point of failure instead of throwing an Error, but there's no way that he's going to agree that nothrow shouldn't mean that exception handling code isn't inserted or that the program should be attempting any kind of clean-up when an Error occurs. He's been _very_ firm about that. An Error is a fatal condition, and he's absolutely adamant that the best course of action at that point is to terminate the program and that the program cannot be trusted to do the right thing once an Error occurs, because by definition, the fact that an Error occured means that the program is in an invalid state. Given his attitude, I do find it a bit weird that he went with throwing Errors rather than just killing the program after printing a message, but it may have something to do with the state of D1 when he made that choice. I don't know. - Jonathan M Davis
Jun 14 2018
next sibling parent reply bauss <jj_1337 live.dk> writes:
On Thursday, 14 June 2018 at 19:06:07 UTC, Jonathan M Davis wrote:
 As I said, personally, I think that the program shut just print 
 and terminate rather than throwing an Error. Walter seems to
It makes perfectly sense for it to throw an error and not just print and terminate. This is especially true for server applications and especially server applications running in the cloud where you do not necessarily have access to a console, but you most likely will have access to a database. So in case of a thrown Error, you can catch it and log it to a database. If it was just printing it would be a lot hard to do such a task, especially when you take permission etc. into account. D would _never_ be fit for large scalable applications if it wasn't possible to retrieve the errors on any system and platform, no matter your limitations.
Jun 14 2018
parent reply wjoe <none example.com> writes:
On Thursday, 14 June 2018 at 22:27:42 UTC, bauss wrote:
 On Thursday, 14 June 2018 at 19:06:07 UTC, Jonathan M Davis 
 wrote:
 So in case of a thrown Error, you can catch it and log it to a 
 database.
No, you can't. Once the Error was thrown the program is in invalid state and you can't assume the logging to database will succeed. If I understood Johnathan's explanations correctly, you can't even be sure that the Error can be caught, since its only purpose is to jump to the print and abort function. This is exactly what I was asking about. Logging, cleanup, executing an emergency stop..not possible.
Jun 15 2018
parent reply bauss <jj_1337 live.dk> writes:
On Friday, 15 June 2018 at 17:25:18 UTC, wjoe wrote:
 On Thursday, 14 June 2018 at 22:27:42 UTC, bauss wrote:
 On Thursday, 14 June 2018 at 19:06:07 UTC, Jonathan M Davis 
 wrote:
 So in case of a thrown Error, you can catch it and log it to a 
 database.
No, you can't. Once the Error was thrown the program is in invalid state and you can't assume the logging to database will succeed.
Sure you can assume it will succeed, BUT in 9/10 cases it will and in those cases it's worth it. I do that and it has proven to work every single time for me. You can't assume it will succeed writing to a log file either. In either cases you just have to try and hope for the best.
Jun 15 2018
next sibling parent reply bauss <jj_1337 live.dk> writes:
On Friday, 15 June 2018 at 17:27:13 UTC, bauss wrote:
 On Friday, 15 June 2018 at 17:25:18 UTC, wjoe wrote:
 On Thursday, 14 June 2018 at 22:27:42 UTC, bauss wrote:
 On Thursday, 14 June 2018 at 19:06:07 UTC, Jonathan M Davis 
 wrote:
 So in case of a thrown Error, you can catch it and log it to 
 a database.
No, you can't. Once the Error was thrown the program is in invalid state and you can't assume the logging to database will succeed.
Sure you can assume it will succeed, BUT in 9/10 cases it will and in those cases it's worth it. I do that and it has proven to work every single time for me. You can't assume it will succeed writing to a log file either. In either cases you just have to try and hope for the best.
There is a reason that I have not gotten rid of this: http://diamondmvc.org/docs/logging/#database-logging It just _works_ most of the time and really helpful when you do not have access to the server and/or the standard output/console.
Jun 15 2018
parent jmh530 <john.michael.hall gmail.com> writes:
On Friday, 15 June 2018 at 17:29:39 UTC, bauss wrote:
 [snip]

 There is a reason that I have not gotten rid of this: 
 http://diamondmvc.org/docs/logging/#database-logging

 It just _works_ most of the time and really helpful when you do 
 not have access to the server and/or the standard 
 output/console.
I wouldn’t doubt that a lot of behavior depends on the current approach of Errors inheriting from Throwable. I’m sure you find value in it the way it is and I bet it would be a pain to change it. Instead, what if they introduced an UnthrowableError that does not inherit from Throwable and just kills the program without unwinding the stack or whatever else people find objectionable currently? The current Error could be re-named Throwable Error and then a new Error could be introduced that has version statements such that whether to call ThrowableError or UnthrowableError depends on switches when you compile. This way you can still have the behavior that you like, though maybe the default would change at some point in the future. The only breaking changes I can figure would be if people are assuming that Error always inherits Throwable, when it wouldn’t if using the UnthrowableError switch.
Jun 15 2018
prev sibling next sibling parent wjoe <none example.com> writes:
On Friday, 15 June 2018 at 17:27:13 UTC, bauss wrote:
 On Friday, 15 June 2018 at 17:25:18 UTC, wjoe wrote:
 On Thursday, 14 June 2018 at 22:27:42 UTC, bauss wrote:
 On Thursday, 14 June 2018 at 19:06:07 UTC, Jonathan M Davis 
 wrote:
 So in case of a thrown Error, you can catch it and log it to 
 a database.
No, you can't. Once the Error was thrown the program is in invalid state and you can't assume the logging to database will succeed.
Sure you can assume it will succeed, BUT in 9/10 cases it will and in those cases it's worth it. I do that and it has proven to work every single time for me. You can't assume it will succeed writing to a log file either. In either cases you just have to try and hope for the best.
Casting away const 'works' too, but is undefined behavior and is not guaranteed to work in future implementations. Likewise, this may work in the current implementation but there's no guarantee that's to stay. At the time of throw Error the program must be considered dead. It sucks, but even if something was logged to the DB you can't rely on this information to be correct. Please read Jonathan's posts further up, he explained the internals and Walter Bright's reasoning in detail.
Jun 15 2018
prev sibling parent Steven Schveighoffer <schveiguy yahoo.com> writes:
On 6/15/18 1:27 PM, bauss wrote:
 On Friday, 15 June 2018 at 17:25:18 UTC, wjoe wrote:
 On Thursday, 14 June 2018 at 22:27:42 UTC, bauss wrote:
 On Thursday, 14 June 2018 at 19:06:07 UTC, Jonathan M Davis wrote:
 So in case of a thrown Error, you can catch it and log it to a database.
No, you can't. Once the Error was thrown the program is in invalid state and you can't assume the logging to database will succeed.
Sure you can assume it will succeed, BUT in 9/10 cases it will and in those cases it's worth it. I do that and it has proven to work every single time for me. You can't assume it will succeed writing to a log file either. In either cases you just have to try and hope for the best.
You can't assume anything when catching an Error. I would not recommend writing to a database in that case. I brought up a similar situation last year: https://forum.dlang.org/post/ogmf1l$2mp8$1 digitalmars.com My solution was simply to replace the array with a wrapper which throws an exception instead. I can't figure out any better way to do it, and really, we can't change the way out-of-bounds errors work. -Steve
Jun 15 2018
prev sibling parent reply wjoe <none example.com> writes:
On Thursday, 14 June 2018 at 19:06:07 UTC, Jonathan M Davis wrote:
 On Thursday, June 14, 2018 18:11:20 wjoe via 
 Digitalmars-d-learn wrote:
 On Wednesday, 13 June 2018 at 20:08:06 UTC, Jonathan M Davis 
 wrote:
 On Wednesday, June 13, 2018 10:56:41 wjoe via
 The idea is that because your program is in an invalid state,
 attempting a graceful shutdown is unsafe. But regardless of
 whether you agree with that, the fact that nothrow doesn't do
 clean-up pretty much ensures that it isn't safe in the 
 general
 case, and nothrow can't do clean-up without negating one of 
 the
 main reasons that it exists in the first place - which is to
that fact also means that a program which threw an Error cannot be debugged anymore; because of invalid state you can neither know, nor assume, that what you see in your debugger or core dump is actually the state which led to the throw.
As I said, personally, I think that the program shut just print and terminate rather than throwing an Error. Walter seems to have designed things from the premise that you could rerun the program to reproduce the problem (which in is usually true with the programs he works on). And in that case, simply getting the error message and stacktrace would be plenty. The problem is when you can't simply rerun the program to reproduce the problem and is why I'm of the opinion that printing and terminating would be better than throwing an Error.
 improve performance by not emitting exception-handling code.
if performance matters so much I would use betterC. 'Improving' performance without profiling and such a trade-off is a bad idea. If it were opt in - yes, I know I will get undebuggable code on error thrown but I want or need the performance gain, fair enough. But instead you are a victim of that implementation whether you like it or not and you might not even be aware about it.
betterC really has nothing to do with performance. It just has to do with avoiding druntime so that you can have C code just link in and use the D code as if it were C (though using it would avoid the issue of Errors, since the runtime wouldn't be there to handle them). And again, Errors are intended for fatal cases, so most of the concerns about doing clean-up are irrelevant. Attempting to recover from an Error is considered to be like attempting to recover from a segfault, which is a terrible, terrible idea. And there are plenty of folks who want to be able to have their code be more performant when it's not using exceptions. So, as long as folks aren't trying to catch Errors, the fact that nothrow doesn't emit the exception handling code really isn't a problem.
What you said earlier: On Monday, 11 June 2018 at 00:47:27 UTC, Jonathan M Davis wrote:
 [...]

 2. If the compiler knows that a function can't throw an 
 Exception, then it doesn't have to insert any of the Exception 
 handling mechanism stuff [...] So, the fact that a function is 
 nothrow gives you a performance benefit, [...]

 - Jonathan M Davis
made me believe that performance is one of the major reasons to use it. No? From the betterC page https://dlang.org/spec/betterc.html section 40.2: --- Not Available D features not available with BetterC: Garbage Collection TypeInfo and ModuleInfo Classes Built-in threading (e.g. core.thread) Dynamic arrays (though slices of static arrays work) and associative arrays Exceptions switch with strings final switch synchronized and core.sync Static module constructors or destructors Struct destructors unittest (testing can be done without the -betterC flag) --- Apart from a few convenience features lost this list reads like a shopping list for performance gain over full fledged D, in the spirit of nothrow omitting exception handling mechanism, to me. You gain from no garbage collection overhead, no vtable overhead, no RTTI overhead, no exception overhead, etc, etc, ... Back in the late 90ies I used to write the lion's share of code in Pascal and implement mission critical algorithms in asm. Worked back then why wouldn't it work today, except that I wouldn't use asm anymore but something like C or betterC. Thus, people who need this kind of performance boost can benefit 2 fold from using betterC. 1. They get to keep most of D's awesomeness, including compile time features, scope statements, RAII, lack of a pre processor, memory safety protections and complete meta programming, are just _some_ of the highlights. And on the other hand 2. they gain by getting rid of a lot the 'performance hogs' like GC, exceptions and more, right? And, with no exceptions altogether they do not need to worry about it at all. I'm sold!
 And out of curiosity again, where would I find this place 
 where the printing and terminating occurs ?
I'd have to go digging in druntime. I don't know. I've probably seen it before, but it's not code that I've dealt with often enough to remember exactly where it is off the top of my head.
druntime. that's a starting point. Thanks.
 Aborting with an error code would be sufficient. No need to 
 print
 anything.
 A backtrace can be obtained in the debugger.
Given that a coredump isn't always generated (and in the case of Windows, I don't know if they even have an equivalent), printing out the same information that gets printed out now would often be desirable. It's just that if it kills the program right there rather than doing any unwinding of the stack, then the coredump is for the state of the program at the point of failure like it arguably should be.
true enough, but I'm sure that the average user wouldn't know what to do with a stack trace in a console and would have closed it long before contacting tech support. We're speaking of rare errors so chances are high that they happen in shipped code. Also, as I noted above in a previous post, there might not even be a console(like device) attached to be able to print the error and stack trace. I also believe that Exceptions and Errors should not carry a message string because 1. the Exception/Error name carries the reason in itself, 2. you can't work well with strings and 3. l18n. It would be better to write that data out into a file and inform the user there was a problem and they should please submit file a and file b to the developer, if possible with a description of what they were doing. That is for Exceptions. In case of an Error just inform them that the program crashed and cannot be recovered and they should just restart it and apologies for the inconvenience. They needn't bother about sending anything because that info is just a dump of invalid program state. Windows creates core dumps, except they use their own terminology. I believe to recall they come in 2 flavors, full- and mini-dumps but to my knowledge, which is older than 12 years, those were uploaded to MS and you needed to have a Visual Studio enterprise level subscription or be a registered developer to be able to retrieve them from MS, that is the ones that were created on machines you don't have access to. I don't know what the current way to do it is. I think it's possible to generate a core dump via gencore, and Windows has MiniDumpWrite or something to that end.
Jun 16 2018
parent reply Jonathan M Davis <newsgroup.d jmdavisprog.com> writes:
On Saturday, June 16, 2018 18:45:53 wjoe via Digitalmars-d-learn wrote:
 What you said earlier:

 On Monday, 11 June 2018 at 00:47:27 UTC, Jonathan M Davis wrote:
 [...]

 2. If the compiler knows that a function can't throw an
 Exception, then it doesn't have to insert any of the Exception
 handling mechanism stuff [...] So, the fact that a function is
 nothrow gives you a performance benefit, [...]

 - Jonathan M Davis
made me believe that performance is one of the major reasons to use it. No? From the betterC page https://dlang.org/spec/betterc.html section 40.2: --- Not Available D features not available with BetterC: Garbage Collection TypeInfo and ModuleInfo Classes Built-in threading (e.g. core.thread) Dynamic arrays (though slices of static arrays work) and associative arrays Exceptions switch with strings final switch synchronized and core.sync Static module constructors or destructors Struct destructors unittest (testing can be done without the -betterC flag) --- Apart from a few convenience features lost this list reads like a shopping list for performance gain over full fledged D, in the spirit of nothrow omitting exception handling mechanism, to me. You gain from no garbage collection overhead, no vtable overhead, no RTTI overhead, no exception overhead, etc, etc, ... Back in the late 90ies I used to write the lion's share of code in Pascal and implement mission critical algorithms in asm. Worked back then why wouldn't it work today, except that I wouldn't use asm anymore but something like C or betterC. Thus, people who need this kind of performance boost can benefit 2 fold from using betterC. 1. They get to keep most of D's awesomeness, including compile time features, scope statements, RAII, lack of a pre processor, memory safety protections and complete meta programming, are just _some_ of the highlights. And on the other hand 2. they gain by getting rid of a lot the 'performance hogs' like GC, exceptions and more, right? And, with no exceptions altogether they do not need to worry about it at all. I'm sold!
The _entire_ point of betterC is to be able to call D code from C code without having to deal with druntime (you can call D code from C code even without betterC, but then you have to worry about initializing and shutting down druntime). Basically every feature that you can't use in betterC is considered a loss, and efforts are being made to make more of them work. There's always going to be a limit to that, and some D features just plain require druntime (just like some of C++'s features require a runtime), but it was never the point of betterC to strip out a bunch of D features. That's just the natural consequence of the goal of being callable from C code without needing to worry about druntime. All of those features that betterC can't use can be avoided in normal D code if you don't want them for whatever reason. nothrow is actually one of the few cases where you have to explicitly do something in order to avoid that list of features that you have there. In the other cases, you just don't use the feature, and the only cost you're paying is the startup and shutdown time for druntime and the few resources that it uses. So, while you might choose to use betterC over concerns about the performance of D features that betterC doesn't allow, that was never the point of betterC. - Jonathan M Davis
Jun 16 2018
parent reply wjoe <none example.com> writes:
On Saturday, 16 June 2018 at 21:25:01 UTC, Jonathan M Davis wrote:
 On Saturday, June 16, 2018 18:45:53 wjoe via 
 Digitalmars-d-learn wrote:
 What you said earlier:

 On Monday, 11 June 2018 at 00:47:27 UTC, Jonathan M Davis 
 wrote:
 [...]

 2. If the compiler knows that a function can't throw an 
 Exception, then it doesn't have to insert any of the 
 Exception handling mechanism stuff [...] So, the fact that a 
 function is nothrow gives you a performance benefit, [...]

 - Jonathan M Davis
made me believe that performance is one of the major reasons to use it. No? From the betterC page https://dlang.org/spec/betterc.html section 40.2: --- Not Available D features not available with BetterC: Garbage Collection TypeInfo and ModuleInfo Classes Built-in threading (e.g. core.thread) Dynamic arrays (though slices of static arrays work) and associative arrays Exceptions switch with strings final switch synchronized and core.sync Static module constructors or destructors Struct destructors unittest (testing can be done without the -betterC flag) --- Apart from a few convenience features lost this list reads like a shopping list for performance gain over full fledged D, in the spirit of nothrow omitting exception handling mechanism, to me. You gain from no garbage collection overhead, no vtable overhead, no RTTI overhead, no exception overhead, etc, etc, ... Back in the late 90ies I used to write the lion's share of code in Pascal and implement mission critical algorithms in asm. Worked back then why wouldn't it work today, except that I wouldn't use asm anymore but something like C or betterC. Thus, people who need this kind of performance boost can benefit 2 fold from using betterC. 1. They get to keep most of D's awesomeness, including compile time features, scope statements, RAII, lack of a pre processor, memory safety protections and complete meta programming, are just _some_ of the highlights. And on the other hand 2. they gain by getting rid of a lot the 'performance hogs' like GC, exceptions and more, right? And, with no exceptions altogether they do not need to worry about it at all. I'm sold!
The _entire_ point of betterC is to be able to call D code from C code without having to deal with druntime (you can call D code from C code even without betterC, but then you have to worry about initializing and shutting down druntime). Basically
BetterC sounds like a C language with tons of features from.. well actually...it sounds like a C language that fixes C's shortcomings. To get that point across it should maybe be called C2D Easy Interop Language.
 every feature that you can't use in betterC is considered a 
 loss, and efforts are being made to make more of them work. 
 There's always going to be a limit to that, and some D features 
 just plain require druntime (just like some of C++'s features 
 require a runtime), but it was never the point of betterC to 
 strip out a bunch of D features. That's just the natural
It is what it is and if what it is is the best tool to fix a problem I would not hesitate to use it to that end. But you make it sound like betterC _should only_ work if actual D code is called otherwise stick with good old C. From the POV of a C programmer most of what betterC offers is a net gain and nothing is a loss because what are they losing by upgrading from C? And in general not paying for something you don't use or need is considered a gain, no?
 consequence of the goal of being callable from C code without 
 needing to worry about druntime.
 All of those features that betterC can't use can be avoided in 
 normal D code if you don't want them for whatever reason. 
 nothrow is actually one of the few cases where you have to 
 explicitly do something in order to avoid that list of features 
 that you have there. In the other cases, you just don't use the 
 feature, and the only cost you're paying is the startup and 
 shutdown time for druntime and the few resources that it uses.
Please tell me. How would I disable just the Error mechanism, for example ? As far as I can tell it's not sufficient that I don't use nothrow in my code because if it was used in phobos or druntime or some other D code I'd have to deal with it. But I know the answer to that. It's not possible because it was never considered because why would anyone want to do that and have the program just crash. Let's say I don't want to deal with OutOfMemoryError. That means essentially I'm losing the GC. Which sucks big time as it is _the_ selling point for me to use D over C. Let's say I didn't agree with RangeError for assoc. Arrays. I imagine it allocates dynamically and hence has a dependency on the GC so I have to consider the OutOfMemoryError headache even if I would agree to RangeError. Solution again don't use it and implement my own. Really, I don't see the difference between not using a feature and not having a feature available; result's the same - I need a solution/replacement.
 So, while you might choose to use betterC over concerns about 
 the performance of D features that betterC doesn't allow, that 
 was never the point of betterC.

 - Jonathan M Davis
Looks like one can only choose the headache to deal with. Now, from the point you make about betterC, it seems like a better idea to abandon ship now and return to C instead of having to deal with similar headaches with betterC in the future.
Jun 18 2018
parent reply Jonathan M Davis <newsgroup.d jmdavisprog.com> writes:
On Monday, June 18, 2018 15:22:48 wjoe via Digitalmars-d-learn wrote:
 On Saturday, 16 June 2018 at 21:25:01 UTC, Jonathan M Davis wrote:
 every feature that you can't use in betterC is considered a
 loss, and efforts are being made to make more of them work.
 There's always going to be a limit to that, and some D features
 just plain require druntime (just like some of C++'s features
 require a runtime), but it was never the point of betterC to
 strip out a bunch of D features. That's just the natural
It is what it is and if what it is is the best tool to fix a problem I would not hesitate to use it to that end. But you make it sound like betterC _should only_ work if actual D code is called otherwise stick with good old C. From the POV of a C programmer most of what betterC offers is a net gain and nothing is a loss because what are they losing by upgrading from C? And in general not paying for something you don't use or need is considered a gain, no?
I'm saying that -betterC is a subset of D that does not include D's runtime, and it includes as many of D's features as it currently can without using the runtime. You can choose to use it and never use normal D code, but the reason that it was created in the first place was so that it would be easier to port C code to D. Without -betterC, you tend to be forced to port the entire program at once, whereas with it, you can port it in pieces and then only switch to normal D once everything has been ported over. But there are some folks who elect to just write code targetting -betterC and who never intend for it to work as normal D code.
 consequence of the goal of being callable from C code without
 needing to worry about druntime.
 All of those features that betterC can't use can be avoided in
 normal D code if you don't want them for whatever reason.
 nothrow is actually one of the few cases where you have to
 explicitly do something in order to avoid that list of features
 that you have there. In the other cases, you just don't use the
 feature, and the only cost you're paying is the startup and
 shutdown time for druntime and the few resources that it uses.
Please tell me. How would I disable just the Error mechanism, for example ? As far as I can tell it's not sufficient that I don't use nothrow in my code because if it was used in phobos or druntime or some other D code I'd have to deal with it.
As with pretty much every other feature, if you don't want any Errors, you just don't use anything that uses it. The same goes with the GC and other features that you might choose to avoid. In some cases, that can be quite limiting, but it is possible to avoid it. It's simply that just like with any feature, avoiding it means losing out on features. The primary difference with nothrow over most other features is that the compiler inserts code by default for Exceptions if nothrow isn't there. So, using nothrow is required to turn that off, whereas for most other features, they only get used if you choose to use them (or use something that uses them). But it has nothing to do with Errors either way. The only way to avoid those is to never use a feature that could throw them (which can be done but would be so limiting that it's probably a waste of time).
 But I know the answer to that. It's not possible because it was
 never considered because why would anyone want to do that and
 have the program just crash.

 Let's say I don't want to deal with OutOfMemoryError. That means
 essentially I'm losing the GC. Which sucks big time as it is
 _the_ selling point for me to use D over C.

 Let's say I didn't agree with RangeError for assoc. Arrays. I
 imagine it allocates dynamically and hence has a dependency on
 the GC so I have to consider the OutOfMemoryError headache even
 if I would agree to RangeError. Solution again don't use it and
 implement my own.

 Really, I don't see the difference between not using a feature
 and not having a feature available; result's the same - I need a
 solution/replacement.
If having the program crash due to an error condition being considered fatal is unacceptable to you, then D will be unacceptable to you - including with -betterC, since in that case, the Errors get turned into failed C assertions that aren't compiled out. So, you won't get the stack unwinding, but your program will be purposefully killed either way, because it encountered an error condition that is considered fatal. You're free to disagree with that approach, and you're free to disagree with which error conditions are considered fatal, but it's part of using D. So, you'll either have to learn to live with that or use a different language. - Jonathan M Davis
Jun 18 2018
parent wjoe <none example.com> writes:
On Monday, 18 June 2018 at 20:23:48 UTC, Jonathan M Davis wrote:
 On Monday, June 18, 2018 15:22:48 wjoe via Digitalmars-d-learn 
 wrote:
 On Saturday, 16 June 2018 at 21:25:01 UTC, Jonathan M Davis 
 wrote:
 every feature that you can't use in betterC is considered a 
 loss, and efforts are being made to make more of them work. 
 There's always going to be a limit to that, and some D 
 features just plain require druntime (just like some of 
 C++'s features require a runtime), but it was never the 
 point of betterC to strip out a bunch of D features. That's 
 just the natural
It is what it is and if what it is is the best tool to fix a problem I would not hesitate to use it to that end. But you make it sound like betterC _should only_ work if actual D code is called otherwise stick with good old C. From the POV of a C programmer most of what betterC offers is a net gain and nothing is a loss because what are they losing by upgrading from C? And in general not paying for something you don't use or need is considered a gain, no?
I'm saying that -betterC is a subset of D that does not include D's runtime, and it includes as many of D's features as it currently can without using the runtime. You can choose to use it and never use normal D code, but the reason that it was created in the first place was so that it would be easier to port C code to D. Without -betterC, you tend to be forced to port the entire program at once, whereas with it, you can port it in pieces and then only switch to normal D once everything has been ported over. But there are some folks who elect to just write code targetting -betterC and who never intend for it to work as normal D code.
That's not how it came across. It came across like the _entire_ purpose of it is to call D stuff without the need to deal with the druntime and nothing else.
 Please tell me. How would I disable just the Error mechanism, 
 for
 example ?
 As far as I can tell it's not sufficient that I don't use 
 nothrow
 in my code because if it was used in phobos or druntime or some
 other D code I'd have to deal with it.
As with pretty much every other feature, if you don't want any Errors, you just don't use anything that uses it. The same goes with the GC and other features that you might choose to avoid. In some cases, that can be quite limiting, but it is possible to avoid it. It's simply that just like with any feature, avoiding it means losing out on features.
So basically everything safe for what is betterC.
 The primary difference with nothrow over most other features is 
 that the compiler inserts code by default for Exceptions if 
 nothrow isn't there. So, using nothrow is required to turn that 
 off, whereas for most other features, they only get used if you 
 choose to use them (or use something that uses them). But it 
 has nothing to do with Errors either way. The only way to avoid 
 those is to never use a feature that could throw them (which 
 can be done but would be so limiting that it's probably a waste 
 of time).

 If having the program crash due to an error condition being 
 considered fatal is unacceptable to you, then D will be
I never made that claim. Unacceptable to me is the implemented mechanism.
 unacceptable to you - including with -betterC, since in that 
 case, the Errors get turned into failed C assertions that 
 aren't compiled out. So, you won't get the stack unwinding, but 
 your program will be purposefully killed either way, because it 
 encountered an error condition that is considered fatal. You're
yes, it will be terminated via sigabrt. Which is the way it's supposed to be. Not to continue running to a function that prints possibly invalid stuff, iff a console like device is attached, and abort in a central, completely unrelated, part of the druntime. If no console is attached, you'll end up with nothing. Seriously, the entire mechanism is contradicting itself. How can it declare program state invalid and unfit to continue at the point the Error was detected and thrown but do it regardless ?
 free to disagree with that approach, and you're free to 
 disagree with which error conditions are considered fatal, but 
 it's part of using D. So, you'll either have to learn to live 
 with that or use a different language.

 - Jonathan M Davis
One could also argue that Exceptions are an integral part of using D and there is really never a situation where you need to turn it off just like there is never a situation where you would catch an Error. Deal with it. If a programming language doesn't so much as to help the developer to be more productive, e.g. by making it easier to squash bugs but, by definition i.e. invalid program state, make it impossible to troubleshoot them, then this language is at least a bad decision from an economic point of view. Which makes it a toy language. I know that much of what can be done actually works in practice but that's not the point. As soon as program is in invalid state it must not continue but immediately abort - and if it continues regardless nothing at all can be relied upon, including what the druntime spits out before aborting because the druntime is, at least by definition, in invalid state, too. And all of this is completely unrelated to my personal opinion.
Jun 19 2018
prev sibling parent reply Kagamin <spam here.lot> writes:
On Wednesday, 13 June 2018 at 02:02:54 UTC, wjoe wrote:
 it is possible to install a signal handler for almost every 
 signal on POSIX, including segfault. The only signal you can't 
 catch is signal 9 - sigkill if memory serves.
 So I could for instance install a clean up handler on a 
 segfault via memset, or a for loop, and then terminate.
What will you do with this? https://github.com/dlang/druntime/blob/master/src/core/internal/abort.d
Jun 13 2018
parent wjoe <none example.com> writes:
On Wednesday, 13 June 2018 at 12:59:27 UTC, Kagamin wrote:
 On Wednesday, 13 June 2018 at 02:02:54 UTC, wjoe wrote:
 it is possible to install a signal handler for almost every 
 signal on POSIX, including segfault. The only signal you can't 
 catch is signal 9 - sigkill if memory serves.
 So I could for instance install a clean up handler on a 
 segfault via memset, or a for loop, and then terminate.
What will you do with this? https://github.com/dlang/druntime/blob/master/src/core/internal/abort.d
Are you asking what I would do in case sigabrt is received by my program instead of sigsegv ? I would install the same cleanup functionality in this handler. Zero out memory, send a signal to stop an engine or whatever mandatory clean up is required and return from the handler. Then let the OS take care of the rest, i.e. terminate the process.
Jun 13 2018
prev sibling parent reply Neia Neutuladh <neia ikeran.org> writes:
On Monday, 11 June 2018 at 00:47:27 UTC, Jonathan M Davis wrote:
 Why do you care about detecting code that can throw an Error? 
 Errors are supposed to kill the program, not get caught. As 
 such, why does it matter if it can throw an Error?
Error is currently used for three different things: * This is a problem that could occur in such a wide range of circumstances, it would make it difficult to use nothrow. * This is a problem severe enough that almost every program would have to abort in these circumstances, so it's reasonable to abort every program here, and damn the few that could handle this type of problem. * This is a problem that someone thinks you might not want to catch when you write `catch (Exception)`, even if it can't be thrown from many places and it wouldn't kill most programs. As an example of the former: I have a service that uses length-prefixed messages on raw sockets. Someone tries to connect to this service with curl. The length of the message is read as 0x4854_5450_2131_2E31 -- ASCII "HTTP/1.1" as an unsigned long. (Or we read a 32-bit length, but we're running on a system with 128MB of RAM and overcommit turned off.) The program might be in an invalid state if this allocation fails. It might not. This depends entirely on how it was written. The runtime is in a valid state. But the exception is OutOfRangeError, which inherits from Error. Similarly, RangeError. There's little conceptual difference between `try {} catch (RangeError) break` and `if (i >= length) break`. But forbidding dynamic array indexing in nothrow code would be rather extreme. On the other hand, a Unicode decoding error is a UnicodeException, not a UnicodeError. I guess whoever wrote that thought invalid Unicode data was sufficiently more common than invalid values in length-prefixed data formats to produce a difference in kind. This isn't obviously wrong, but it does look like something that could use justification.
Jun 12 2018
parent reply Jonathan M Davis <newsgroup.d jmdavisprog.com> writes:
On Tuesday, June 12, 2018 23:32:55 Neia Neutuladh via Digitalmars-d-learn 
wrote:
 On Monday, 11 June 2018 at 00:47:27 UTC, Jonathan M Davis wrote:
 Why do you care about detecting code that can throw an Error?
 Errors are supposed to kill the program, not get caught. As
 such, why does it matter if it can throw an Error?
Error is currently used for three different things: * This is a problem that could occur in such a wide range of circumstances, it would make it difficult to use nothrow.
This is not a valid reason to use Error. Error is specifically for cases where failure is a bug in the program or where the program cannot recover from the failure and must be terminated. If a program is simply trying to be able to use nothrow, then it needs to use an error-hanlding mechanism other than exceptions. Not only is this how Errors are designed to work, but the fact that proper clean-up is not guaranteed when a non-Exception Throwable is thrown means that attempting to continue after anything other than an Exception is thrown is incredibly risky, potentially putting your program in an invalid state and causing who knows what bugs. And nothrow functions are a prime case where clean-up is definitely not done for non-Exceptions, because avoiding the extra code necessary to do that clean-up is one of the main reasons that nothrow exists in the first place.
 * This is a problem severe enough that almost every program would
 have to abort in these circumstances, so it's reasonable to abort
 every program here, and damn the few that could handle this type
 of problem.
 * This is a problem that someone thinks you might not want to
 catch when you write `catch (Exception)`, even if it can't be
 thrown from many places and it wouldn't kill most programs.

 As an example of the former: I have a service that uses
 length-prefixed messages on raw sockets. Someone tries to connect
 to this service with curl. The length of the message is read as
 0x4854_5450_2131_2E31 -- ASCII "HTTP/1.1" as an unsigned long.

 (Or we read a 32-bit length, but we're running on a system with
 128MB of RAM and overcommit turned off.)

 The program might be in an invalid state if this allocation
 fails. It might not. This depends entirely on how it was written.
 The runtime is in a valid state. But the exception is
 OutOfRangeError, which inherits from Error.
It's possible to write programs that check and handle running out of memory, but most programs don't, and usually, if a program runs out of memory, it can't do anything about it and can't function properly at that point. As such, D's new was designed with the idea that failed memory allocations are fatal to the program, and any program that wants to be able to handle the case where it runs out of memory but somehow is able to continue to function shouldn't be using the GC for such allocations. But programs that can even attempt to recover from running out of memory are going to be rare, and having running out of memory throw an Exception would likely cause all kinds of fun problems in the typical case, since if anything catches the Exception, that could easily trigger a chain reaction of nasty stuff. The catch almost certainly wouldn't be properly attempting to recover from running out of memory, and the program would almost certainly assume that allocations always succeeded rather than exiting on allocation failure. So, continuing at that point would effectively put the program in an invalid state. Also, if simply allocating memory could throw and Exception, then that would pretty much kill nothrow, since it would only be viable in nogc code. So, while treating all failed memory allocations as fatal is certainly a debtable choice, it does fit what most programs do quite well. But either way, the result is that anyone programming in D who might want to recover from memory allocation failures needs to take that design into account and really should be avoiding the GC for such allocations.
 Similarly, RangeError. There's little conceptual difference
 between `try {} catch (RangeError) break` and `if (i >= length)
 break`. But forbidding dynamic array indexing in nothrow code
 would be rather extreme.
The idea is that it's a bug in your code if you ever index an array with an index that's out-of-bounds. If there's any risk of indexing incorrectly, then the program needs to check for it, or it's a bug in the program. Most indices are not taken from program input, so treating them as input in the general case wouldn't really make sense - plus, of course, treating them as program input in the general case would mean using Exceptions, which would then kill nothrow. In the end, it just makes more sense to treat invalid indices as programming errors. So, in the cases where an index is actually derived from program input, the program must check the index, or it's a bug, and the result will be an Error being thrown.
 On the other hand, a Unicode decoding error is a
 UnicodeException, not a UnicodeError. I guess whoever wrote that
 thought invalid Unicode data was sufficiently more common than
 invalid values in length-prefixed data formats to produce a
 difference in kind. This isn't obviously wrong, but it does look
 like something that could use justification.
The difference is that incorrectly indexing an array is considered a bug in your program, whereas bad Unicode is almost always bad program input. Bad input to a program is not a bug in the program. Assuming that the input is valid and treating it that way when it might be invalid would be a bug in the program, but code that validates program input is not buggy because it determines that the input is bad. As such, throwing an Error on bad Unicode doesn't make much sense. The only way that it would make sense to treat invalid Unicode as a bug in the program would be if it were reasonable to assume that all Unicode was validated before ever being passed to std.utf.decode or std.utf.stride. - Jonathan M Davis
Jun 12 2018
parent Neia Neutuladh <neia ikeran.org> writes:
On Wednesday, 13 June 2018 at 00:38:55 UTC, Jonathan M Davis 
wrote:
 It's possible to write programs that check and handle running 
 out of memory, but most programs don't, and usually, if a 
 program runs out of memory, it can't do anything about it and 
 can't function properly at that point.
Simulations that run out of memory are likely unable to recover from OutOfMemoryError. Transactional programs like webservers are likely to run out of memory due to an unusually large request.
 The idea is that it's a bug in your code if you ever index an 
 array with an index that's out-of-bounds. If there's any risk 
 of indexing incorrectly, then the program needs to check for 
 it, or it's a bug in the program. Most indices are not taken 
 from program input, so treating them as input in the general 
 case wouldn't really make sense
The case I find is almost invariably a hard-coded index into input data, like a CSV file that is supposed to have ten columns but only has eight. This is often a bug in my program simply because most exceptions I encounter are bugs in my program.
 - plus, of course, treating them as program input in the 
 general case would mean using Exceptions, which would then kill 
 nothrow.
Which goes back to my point of problems that could be caused by too wide a range of code being Errors.
Jun 12 2018
prev sibling next sibling parent Kagamin <spam here.lot> writes:
On Sunday, 10 June 2018 at 23:59:17 UTC, Bauss wrote:
 To me it would be so much more useful if you could detect code 
 that could possibly throw Error.
Such things are usually done by formal verification systems like F*, and I suppose Ada 2012 has it to some extent too. Though I suspect it's not easy to use, less easy than rust.
Jun 12 2018
prev sibling parent reply Steven Schveighoffer <schveiguy yahoo.com> writes:
On 6/10/18 7:59 PM, Bauss wrote:
 What is the point of nothrow if it can only detect when Exception is 
 thrown and not when Error is thrown?
 
 It seems like the attribute is useless because you can't really use it 
 as protection to write bugless, safe code since the nasty bugs will pass 
 by just fine.
Array invalid index throws Error, and asserts throw Error. I'm not sure how much you could accomplish without such features. In fact, I'd consider these ESSENTIAL to writing safe code. Bug-free code is a myth :) -Steve
Jun 12 2018
parent reply Bauss <jj_1337 live.dk> writes:
On Tuesday, 12 June 2018 at 14:19:42 UTC, Steven Schveighoffer 
wrote:
 On 6/10/18 7:59 PM, Bauss wrote:
 What is the point of nothrow if it can only detect when 
 Exception is thrown and not when Error is thrown?
 
 It seems like the attribute is useless because you can't 
 really use it as protection to write bugless, safe code since 
 the nasty bugs will pass by just fine.
Array invalid index throws Error, and asserts throw Error. I'm not sure how much you could accomplish without such features. In fact, I'd consider these ESSENTIAL to writing safe code. Bug-free code is a myth :) -Steve
Both are cases that the compiler __could__ warn you about potential possibility of them being thrown and thus allowing you to write code that makes sure it doesn't happen. Ex. int a = array[400]; Could yield a warning stating a possible a out of bounds error. Where: int a = array.length >= 401 ? array[400] : 0; Wouldn't because you're handling the case. What I'm trying to say it would be nice to catch certain situations like that (of course not possible with all) because you'll end up having to handle them anyway after the error is thrown.
Jun 12 2018
next sibling parent Steven Schveighoffer <schveiguy yahoo.com> writes:
On 6/12/18 11:48 AM, Bauss wrote:
 On Tuesday, 12 June 2018 at 14:19:42 UTC, Steven Schveighoffer wrote:
 On 6/10/18 7:59 PM, Bauss wrote:
 What is the point of nothrow if it can only detect when Exception is 
 thrown and not when Error is thrown?

 It seems like the attribute is useless because you can't really use 
 it as protection to write bugless, safe code since the nasty bugs 
 will pass by just fine.
Array invalid index throws Error, and asserts throw Error. I'm not sure how much you could accomplish without such features. In fact, I'd consider these ESSENTIAL to writing safe code. Bug-free code is a myth :)
Both are cases that the compiler __could__ warn you about potential possibility of them being thrown and thus allowing you to write code that makes sure it doesn't happen. Ex. int a = array[400]; Could yield a warning stating a possible a out of bounds error. Where: int a = array.length >= 401 ? array[400] : 0; Wouldn't because you're handling the case. What I'm trying to say it would be nice to catch certain situations like that (of course not possible with all) because you'll end up having to handle them anyway after the error is thrown.
It's trivial to get into situations that are provably not going to throw an error, but for which the compiler still is going to insert the check. I think it would end up being more annoying than useful. If I had it my way, array bounds checks would not be an error, they would be an exception (and not be turned off ever for actual arrays). -Steve
Jun 12 2018
prev sibling parent wjoe <none example.com> writes:
On Tuesday, 12 June 2018 at 15:48:58 UTC, Bauss wrote:
 Ex.

 int a = array[400];

 Could yield a warning stating a possible a out of bounds error.

 Where:

 int a = array.length >= 401 ? array[400] : 0;
looks to me like a crash guard. Similar to something like this void fn(Foo* foo) { if (foo) //do stuff } program now crashes somewhere else when foo is null or invalid.
Jun 12 2018