www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - halt with optional message?

reply bearophile <bearophileHUGS lycos.com> writes:
Is it possible, and is it a good/wise idea to modify D a bit so that in release
mode this:

assert(0);

becomes a HLT, while in release mode this 

assert(0, "message");

Becomes the same thing as:

core.stdc.stdlib.puts("message");
HTL

?

What I asking here is support for optional messages in assert(0) too, and if
it's a good idea.

Note: writing puts before an assert(0) in D code is not the same thing, because
you are not supposed to be able to use puts in a pure function:

void foo() pure {
    puts("message");
    assert(0);
}

Bye,
bearophile
Aug 11 2011
next sibling parent reply "Vladimir Panteleev" <vladimir thecybershadow.net> writes:
On Thu, 11 Aug 2011 14:00:03 +0300, bearophile <bearophileHUGS lycos.com>  
wrote:

 Is it possible, and is it a good/wise idea to modify D a bit so that in  
 release mode this:

Assert reasons should never be in release executables. Release executables are often meant for redistribution and shouldn't contain messages intended for debugging. A simple function would be better suited for this, I think. -- Best regards, Vladimir mailto:vladimir thecybershadow.net
Aug 11 2011
parent bearophile <bearophileHUGS lycos.com> writes:
Vladimir Panteleev:

 Assert reasons should never be in release executables. Release executables  
 are often meant for redistribution and shouldn't contain messages intended  
 for debugging.

Contracts contain asserts, sometimes asserts are kept in the released binaries too (dmd has many asserts active) and those asserts hopefully contain an error message for debugging. How do you remove those error messages? I don't think that removing them improves the program and its usage in any way. Also, here we are discussing about assert(0), it's a different kind of assert, that is kept in release mode too. If the program prints a debugging message and the user tells me the error message (this is right what has just happened to me), I am able to know what assert(0) has fired even if the user is not using a debugger. So I don't think you are right. A simple function would be better suited for this, I think. puts() is not pure, so if you add a puts() in a function, the function can't be pure. So the function that calls this function can't be pure... Bye, bearophile
Aug 11 2011
prev sibling next sibling parent reply "Vladimir Panteleev" <vladimir thecybershadow.net> writes:
On Thu, 11 Aug 2011 14:20:46 +0300, bearophile <bearophileHUGS lycos.com>  
wrote:

 Contracts contain asserts,

But contracts are removed in release executables too, no?
 sometimes asserts are kept in the released binaries too (dmd has many  
 asserts active) and those asserts hopefully contain an error message for  
 debugging.

Consider: regular asserts are removed from release executables. assert(0) compiles to a HLT instead of nothing merely because it has practically no overhead (only one byte of machine code)! I think you're confusing the purpose of asserts with something else again. Besides, there are some who think that the special case of assert(0) is confusing/inconsistent with regular asserts enough, why do you want to enlarge that distinction even more?
 I don't think that removing them improves the program and its usage in  
 any way.

If I'm writing a commercial, closed-source program meant for redistribution, including any unnecessary information that helps reversers to understand how the program works is just stupid.
 Also, here we are discussing about assert(0), it's a different kind of  
 assert, that is kept in release mode too. If the program prints a  
 debugging message and the user tells me the error message (this is right  
 what has just happened to me), I am able to know what assert(0) has  
 fired even if the user is not using a debugger. So I don't think you are  
 right.

You're not supposed to use -release if you want to know what happened. Failed asserts in release executables should never happen, unless your program is buggy. If your program is buggy, don't use -release until you've debugged it.
 puts() is not pure, so if you add a puts() in a function, the function  
 can't be pure. So the function that calls this function can't be pure...

This is the least of my concern. -- Best regards, Vladimir mailto:vladimir thecybershadow.net
Aug 11 2011
parent reply bearophile <bearophileHUGS lycos.com> writes:
Vladimir Panteleev:

 Besides, there are some who think that the special case of assert(0) is  
 confusing/inconsistent with regular asserts enough,

The discussion ended with no changes in D because I think for Walter it's a problem not large enough to be worth a change in D.
 If I'm writing a commercial, closed-source program meant for  
 redistribution, including any unnecessary information that helps reversers  
 to understand how the program works is just stupid.

Then you don't add a message to assert(0), so it keeps being translated with just an efficient HLT. The purpose of D programs is varied, there are not just closed source programs to sell. The user of a small D program I have recently written was sitting in a room near mine. He has hit an assert, he has told me what the message is, and I have fixed the code and sent him the fixed binary. The program is now working, it seems.
 Failed asserts in release executables should never happen, unless your  
 program is buggy. If your program is buggy, don't use -release until  
 you've debugged it.

Sometimes I think it's not buggy, but it contains one or more bugs :-(
 This is the least of my concern.

I'm trying to use purity more and more :-) It helps me avoid some troubles. As more and more stuff in Phobos becomes pure, I suggest you to use this attribute more in your code. The purpose of this thread was not just to ask for a feature (I use Bugzilla for that), but also to know if this is first of all a good idea. Thank you for your answers, I am seeing the situation a bit better now. Bye, bearophile
Aug 11 2011
parent simendsjo <simendsjo gmail.com> writes:
On 11.08.2011 14:56, Vladimir Panteleev wrote:
 On Thu, 11 Aug 2011 14:59:03 +0300, Vladimir Panteleev
 <vladimir thecybershadow.net> wrote:

 I don't see what the problem is. Is your program buggy? Don't use
 -release. Are you done fixing bugs? Use -release to remove pointless
 clutter. Is the program segfaulting on a user's PC? Send him a debug
 build!

By the way, I'd like to add some thoughts on how wrong I think it is to rely on a single debugging feature like this in release builds. Asserts (both conditional and unconditional), contracts, invariants and native language features such as array bounds checking all work together to find bugs as soon as possible. If you get an error message on an assert(0) and you attempt to debug it from that, you may be led on a wild goose chase, because the program might have actually failed much earlier and ran for a while in an undetermined state, corrupting memory left and right or spreading internal state inconsistencies uncaught by invariants. I know about this all too well from my experience of debugging memory corruption - the garbage collector is compiled with no invariants as its performance is critical, but recompiling my program with a version of Phobos with contracts enabled would have saved me tracing a few steps to find the source of corruption.

Which reminds me.. Why isn't a phobos shipped with a precompiled version containing contracts?
Aug 11 2011
prev sibling next sibling parent "Vladimir Panteleev" <vladimir thecybershadow.net> writes:
On Thu, 11 Aug 2011 14:55:29 +0300, bearophile <bearophileHUGS lycos.com>  
wrote:

 If I'm writing a commercial, closed-source program meant for
 redistribution, including any unnecessary information that helps  
 reversers
 to understand how the program works is just stupid.

Then you don't add a message to assert(0), so it keeps being translated with just an efficient HLT.

But I want a message in debug mode! Are you saying that your use case is so much more common than messages meant only for the debug development stage?
 The purpose of D programs is varied, there are not just closed source  
 programs to sell. The user of a small D program I have recently written  
 was sitting in a room near mine. He has hit an assert, he has told me  
 what the message is, and I have fixed the code and sent him the fixed  
 binary. The program is now working, it seems.

I don't see what the problem is. Is your program buggy? Don't use -release. Are you done fixing bugs? Use -release to remove pointless clutter. Is the program segfaulting on a user's PC? Send him a debug build!
 Failed asserts in release executables should never happen, unless your
 program is buggy. If your program is buggy, don't use -release until
 you've debugged it.

Sometimes I think it's not buggy, but it contains one or more bugs :-(

That's YOUR problem. :) -- Best regards, Vladimir mailto:vladimir thecybershadow.net
Aug 11 2011
prev sibling next sibling parent "Vladimir Panteleev" <vladimir thecybershadow.net> writes:
On Thu, 11 Aug 2011 14:59:03 +0300, Vladimir Panteleev  
<vladimir thecybershadow.net> wrote:

 I don't see what the problem is. Is your program buggy? Don't use  
 -release. Are you done fixing bugs? Use -release to remove pointless  
 clutter. Is the program segfaulting on a user's PC? Send him a debug  
 build!

By the way, I'd like to add some thoughts on how wrong I think it is to rely on a single debugging feature like this in release builds. Asserts (both conditional and unconditional), contracts, invariants and native language features such as array bounds checking all work together to find bugs as soon as possible. If you get an error message on an assert(0) and you attempt to debug it from that, you may be led on a wild goose chase, because the program might have actually failed much earlier and ran for a while in an undetermined state, corrupting memory left and right or spreading internal state inconsistencies uncaught by invariants. I know about this all too well from my experience of debugging memory corruption - the garbage collector is compiled with no invariants as its performance is critical, but recompiling my program with a version of Phobos with contracts enabled would have saved me tracing a few steps to find the source of corruption. -- Best regards, Vladimir mailto:vladimir thecybershadow.net
Aug 11 2011
prev sibling next sibling parent reply Timon Gehr <timon.gehr gmx.ch> writes:
bearophile wrote:
 Is it possible, and is it a good/wise idea to modify D a bit so that in
 release mode this:

 assert(0);

 becomes a HLT, while in release mode this

 assert(0, "message");

 Becomes the same thing as:

 core.stdc.stdlib.puts("message");
 HTL

 ?

 What I asking here is support for optional messages in assert(0) too, and
 if it's a good idea.

 Note: writing puts before an assert(0) in D code is not the same thing,
 because you are not supposed to be able to use puts in a pure function:

 void foo() pure {
     puts("message");
     assert(0);
 }

 Bye,
 bearophile

I don't think it is a very common need to still have a message for assert(0) when turning off other assertions. But you can solve your problem by circumventing the type system: void assert0impl(string msg){ writeln(msg); assert(0); } void assert0(string msg)pure nothrow trusted{ (cast(void function(string)pure nothrow trusted)&assert0impl)(msg); } Maybe a better solution would be to have noreturn functions in the language. (or, prettier, a type of which no values exist). Cheers, -Timon
Aug 11 2011
next sibling parent Timon Gehr <timon.gehr gmx.ch> writes:
bearophile wrote:
 void foo() pure {
     puts("message");
     assert(0);
 }

BTW, that that function is any less pure than void foo() pure { assert(0); } Is imho just a QOI issue.
Aug 11 2011
prev sibling parent bearophile <bearophileHUGS lycos.com> writes:
Timon Gehr:

 Maybe a better solution would be to have  noreturn functions in the language.
(or,
 prettier, a type of which no values exist).

Yeah. Recently Walter has added something like that inside the DMD source code. GNU C uses (noreturn). Bye, bearophile
Aug 11 2011
prev sibling next sibling parent reply "Jonathan M Davis" <jmdavisProg gmx.com> writes:
On Thursday, August 11, 2011 06:58 simendsjo wrote:
 On 11.08.2011 14:56, Vladimir Panteleev wrote:
 On Thu, 11 Aug 2011 14:59:03 +0300, Vladimir Panteleev
 
 <vladimir thecybershadow.net> wrote:
 I don't see what the problem is. Is your program buggy? Don't use
 -release. Are you done fixing bugs? Use -release to remove pointless
 clutter. Is the program segfaulting on a user's PC? Send him a debug
 build!

By the way, I'd like to add some thoughts on how wrong I think it is to rely on a single debugging feature like this in release builds. Asserts (both conditional and unconditional), contracts, invariants and native language features such as array bounds checking all work together to find bugs as soon as possible. If you get an error message on an assert(0) and you attempt to debug it from that, you may be led on a wild goose chase, because the program might have actually failed much earlier and ran for a while in an undetermined state, corrupting memory left and right or spreading internal state inconsistencies uncaught by invariants. I know about this all too well from my experience of debugging memory corruption - the garbage collector is compiled with no invariants as its performance is critical, but recompiling my program with a version of Phobos with contracts enabled would have saved me tracing a few steps to find the source of corruption.

Which reminds me.. Why isn't a phobos shipped with a precompiled version containing contracts?

Because that would be inefficient. As it stands, there's no way to tell the compiler, "use this library in release mode but use this library in debug mode." So, you're stuck with one or the other, and going with the debug version of Phobos would negatively impact all D programs as far as efficiency goes. We _could_ have the debug version in a separate folder with instructions somewhere telling you to adjust your build scripts so that you use one for debug and one for release, but that does complicate things. It also increases the size of the zip file, and I don't think that it makes sense at all with an installer or Linux package. Now, the _templated_ code in Phobos will use contracts just fine (as long you're not compiling your project in release mode), since that's compiled when the programmer uses it rather than compiled into the library itself. So, most of the cases where you actually need contracts based on what the programmer using Phobos is doing (as opposed to Phobos itself) should still work. To actually, reasonably distribute Phobos in a debug and release state would probably necessitate setting it up so that dmd was smart enough to use one set of libraries in release mode and another in debug mode. - Jonathan M Davis
Aug 11 2011
next sibling parent kennytm <kennytm gmail.com> writes:
"Jonathan M Davis" <jmdavisProg gmx.com> wrote:
[snip] 
 Because that would be inefficient. As it stands, there's no way to
 tell the 
 compiler, "use this library in release mode but use this library in
 debug 
 mode." 

Can't you use -defaultlib and -debuglib?
Aug 11 2011
prev sibling next sibling parent "Jonathan M Davis" <jmdavisProg gmx.com> writes:
On Thursday, August 11, 2011 11:00 kennytm wrote:
 "Jonathan M Davis" <jmdavisProg gmx.com> wrote:
 [snip]
 
 Because that would be inefficient. As it stands, there's no way to
 tell the
 compiler, "use this library in release mode but use this library in
 debug
 mode."

Can't you use -defaultlib and -debuglib?

So, you could. I didn't know that they existed. I wonder if they were added after previous discussions about this issue, since in previous discussions, those flags never came up, and I've never noticed them before. Just the same, I'm not sure if we actually want to distribute a non-release version of libphobos though. I expect that it would significantly increase the size of the zip file as well as create some level of confusion, and without a standard place to put debug versions of a library, I don't see how it would work with the distro packages. All someone has to do is compile druntime and Phobos to get it themselves, and all of the source is right there. However, they _would_ have to compile the source, which while relatively easy is not something which is immediately obvious how to do. So, I don't know. Maybe they could be released as libphobos_debug.a and go in the same place as libphobos.a (along with whatever the equivalents would be on Windows). I'm not quite sure how this is dealt with in C/C++ land though. IIUC, the closest that you get to a debug build on Linux without building a library yourself is installing the version of a library which includes debug symbols (but it's still compiled in release mode aside from that I believe). I don't know what the situation is on Windows. So, I don't know. On the whole, I don't consider it to be a big deal, but I could see why someone would want it. But I really don't know the best way to handle the situation. - Jonathan M Davis
Aug 11 2011
prev sibling next sibling parent Sean Kelly <sean invisibleduck.org> writes:
On Aug 11, 2011, at 11:22 AM, Jonathan M Davis wrote:

 On Thursday, August 11, 2011 11:00 kennytm wrote:
 "Jonathan M Davis" <jmdavisProg gmx.com> wrote:
 [snip]
=20
 Because that would be inefficient. As it stands, there's no way to
 tell the
 compiler, "use this library in release mode but use this library in
 debug
 mode."

Can't you use -defaultlib and -debuglib?

So, you could. I didn't know that they existed. I wonder if they were =

 after previous discussions about this issue, since in previous =

 those flags never came up, and I've never noticed them before.=20

They were added to support the use of third-party standard libs after = being requested by the Tango folks (me, actually) years ago.=
Aug 11 2011
prev sibling parent Jonathan M Davis <jmdavisProg gmx.com> writes:
On Thursday, August 11, 2011 12:44:02 Sean Kelly wrote:
 On Aug 11, 2011, at 11:22 AM, Jonathan M Davis wrote:
 On Thursday, August 11, 2011 11:00 kennytm wrote:
 "Jonathan M Davis" <jmdavisProg gmx.com> wrote:
 [snip]
 
 Because that would be inefficient. As it stands, there's no way to
 tell the
 compiler, "use this library in release mode but use this library in
 debug
 mode."

Can't you use -defaultlib and -debuglib?

So, you could. I didn't know that they existed. I wonder if they were added after previous discussions about this issue, since in previous discussions, those flags never came up, and I've never noticed them before.

They were added to support the use of third-party standard libs after being requested by the Tango folks (me, actually) years ago.

Well, obviously no one discussing this issue in the past has paid enough attention to dmd's flags, since no one has ever brought it up. Obviously, I need to pay more attention. - Jonathan M Davis
Aug 11 2011
prev sibling next sibling parent reply "Vladimir Panteleev" <vladimir thecybershadow.net> writes:
On Thu, 11 Aug 2011 20:44:15 +0300, Jonathan M Davis <jmdavisProg gmx.com>  
wrote:

 As it stands, there's no way to tell the compiler, "use this library in  
 release mode but use this library in debug mode."

Would it be possible to use something like pragma(lib) or pragma(link) to specify the Phobos version to link against? -- Best regards, Vladimir mailto:vladimir thecybershadow.net
Aug 11 2011
parent bearophile <bearophileHUGS lycos.com> writes:
Vladimir Panteleev:

 Would it be possible to use something like pragma(lib) or pragma(link) to  
 specify the Phobos version to link against?

Andrei likes general solutions. What you write suggests me that maybe there is a solution to a more general problem. Instead of modifying DMD to support just two pre-compiled Phobos, maybe it is possible to add D/DMD a more general feature to support the two debug/release pairs even with user-defined libraries. Bye, bearophile
Aug 11 2011
prev sibling parent reply Sean Kelly <sean invisibleduck.org> writes:
On Aug 11, 2011, at 10:44 AM, Jonathan M Davis wrote:

 On Thursday, August 11, 2011 06:58 simendsjo wrote:
 On 11.08.2011 14:56, Vladimir Panteleev wrote:
=20
 Which reminds me.. Why isn't a phobos shipped with a precompiled =


 containing contracts?

Because that would be inefficient. As it stands, there's no way to =

 compiler, "use this library in release mode but use this library in =

 mode."

Yes there is: -debuglib. I have a few issues with this as DMD currently works, though. First, = whether to use checked vs. unchecked code has nothing to do with whether = it's "release" or "non-release". The current switch name really has to = be changed to -unchecked so people aren't tricked into thinking that = shipping checked code is a bad thing. Once this is done, the DMD = switches -defaultlib and -debuglib could be changed to -defaultlib and = -uncheckedlib. Whether or not the user supplies the -debug switch = should mean nothing insofar as which external library is used. More = important is that checking be used throughout or not at all. Once this = is sorted, I'd gladly build and ship multiple versions of druntime for = these configs.=
Aug 11 2011
parent bearophile <bearophileHUGS lycos.com> writes:
Sean Kelly:

 The current switch name really has to be changed to

Lately Walter seems to appreciate pull requests a lot. So is someone willing to write such patch (it doesn't look too much complex to do)? Bye, bearophile
Aug 11 2011