Jump to page: 1 2 3
Thread overview
Where did my contracts go?
Aug 15, 2005
AJG
Aug 15, 2005
Charles
Aug 16, 2005
AJG
Aug 16, 2005
Charles
Aug 15, 2005
Ben Hinkle
Aug 15, 2005
AJG
Aug 15, 2005
Derek Parnell
Aug 16, 2005
AJG
Aug 16, 2005
Derek Parnell
Aug 15, 2005
Derek Parnell
Aug 16, 2005
Hasan Aljudy
Aug 16, 2005
Derek Parnell
Aug 16, 2005
AJG
Aug 16, 2005
Mike Parker
Aug 16, 2005
AJG
Aug 17, 2005
Derek Parnell
Aug 17, 2005
AJG
Aug 17, 2005
Sean Kelly
Aug 17, 2005
AJG
Aug 18, 2005
Sean Kelly
Aug 18, 2005
AJG
Aug 19, 2005
Derek Parnell
Aug 19, 2005
AJG
Aug 19, 2005
AJG
Aug 19, 2005
Mike Parker
Aug 20, 2005
AJG
Aug 20, 2005
Mike Parker
August 15, 2005
Hi,

First, I was happily coding in D under -debug. Then, I started using std.boxer which requires that I use -release because of unresolved linking.

So I add -release (in _addition_ to -debug) and all hell breaks lose.

1) asserts no longer display anything meaningful; they segfault.
2) pre-condition (in) contracts disappear altogether.

What's going on? This seems extremely unreasonable to me.

I understand that some crazy people don't like safety contracts in their -release code, but I specified -debug too.

Would it be possible to restore these 2 contracts, properly (no segfault), at least under -debug? Please? I'm on linux w/ 129.

Thank you,
--AJG.





August 15, 2005
I agree , I think contracts should be completely seperate from 'release' and 'debug'.   Looking at the front end ( mars.c : 385 ) , it wouldn't take much at all , just an extra command line argument , -contracts or some such.

This has been talked about before , not sure what the outcome was.

Charlie

P.S. Also , in the source it has useAssert parameter set to true if unittests are on , maybe try that ?

"AJG" <AJG_member@pathlink.com> wrote in message news:ddqhqm$19a3$1@digitaldaemon.com...
> Hi,
>
> First, I was happily coding in D under -debug. Then, I started using
std.boxer
> which requires that I use -release because of unresolved linking.
>
> So I add -release (in _addition_ to -debug) and all hell breaks lose.
>
> 1) asserts no longer display anything meaningful; they segfault.
> 2) pre-condition (in) contracts disappear altogether.
>
> What's going on? This seems extremely unreasonable to me.
>
> I understand that some crazy people don't like safety contracts in their -release code, but I specified -debug too.
>
> Would it be possible to restore these 2 contracts, properly (no segfault),
at
> least under -debug? Please? I'm on linux w/ 129.
>
> Thank you,
> --AJG.
>
>
>
>
>


August 15, 2005
"AJG" <AJG_member@pathlink.com> wrote in message news:ddqhqm$19a3$1@digitaldaemon.com...
> Hi,
>
> First, I was happily coding in D under -debug. Then, I started using
> std.boxer
> which requires that I use -release because of unresolved linking.
>
> So I add -release (in _addition_ to -debug) and all hell breaks lose.
>
> 1) asserts no longer display anything meaningful; they segfault.
> 2) pre-condition (in) contracts disappear altogether.
>
> What's going on? This seems extremely unreasonable to me.
>
> I understand that some crazy people don't like safety contracts in their -release code, but I specified -debug too.
>
> Would it be possible to restore these 2 contracts, properly (no segfault),
> at
> least under -debug? Please? I'm on linux w/ 129.
>
> Thank you,
> --AJG.

If you want to use boxer in a module with asserts turned on you have to recompile phobos with asserts turned on (ie without -release). Edit the makfile in dmd/src/phobos to uncomment the unittest DFLAGS variable and run make.


August 15, 2005
Hi,

>If you want to use boxer in a module with asserts turned on you have to recompile phobos with asserts turned on (ie without -release). Edit the makfile in dmd/src/phobos to uncomment the unittest DFLAGS variable and run make.

While this helps with std.boxer specifically, it doesn't help with contracts in general. Before anything, are the following three things clearly defined anywhere?

A) -debug
B) -release
C) -debug -release
D) -release -debug (if different from C).

In addition, I'm really surprised (read: annoyed) that release/debug have an effect on contracts. This is faulty logic IMHO.

It would make more sense to do the following:

# void Foo(int a) in {
#     assert(a == 42); // Stays there forever.
#     debug assert(someExpensiveCheck(a)); // Removed in release.
# } body { /* body */ }

Or perhaps, something like:

# void Foo(int a) debug in { // All removed in release.
#     assert(a == 42);
#     assert(someExpensiveCheck(a));
# } body { /* body */ }

Thanks,
--AJG.


August 15, 2005
On Mon, 15 Aug 2005 17:02:14 +0000 (UTC), AJG wrote:

> Hi,
> 
> First, I was happily coding in D under -debug. Then, I started using std.boxer which requires that I use -release because of unresolved linking.
> 
> So I add -release (in _addition_ to -debug) and all hell breaks lose.
> 
> 1) asserts no longer display anything meaningful; they segfault.
> 2) pre-condition (in) contracts disappear altogether.
> 
> What's going on? This seems extremely unreasonable to me.
> 
> I understand that some crazy people don't like safety contracts in their -release code, but I specified -debug too.
> 
> Would it be possible to restore these 2 contracts, properly (no segfault), at least under -debug? Please? I'm on linux w/ 129.

Believe it or not, but this is a philosophical discussion.

Walter's philosophy (and yes, I'm speculating here) is that the purpose of the in{} and out{} blocks and assert() calls is to alert the developer of any mistakes in their code logic. They are not to be used to detect bad data. The "-release" effects these constructs because by the time you create the production edition, all the code logic has been validated.

This means that if you require that the end user is alerted to logic errors, your choices are that you supply them with a non-release edition and/or you code your 'contracts' outside of the in{}, out{}, and assert() constructs. The choice is yours.

Further more, validation of user data should never be coded inside contract constructs as these are designed to detect *logic* mistakes and not data problems. In short, you are encouraged to detect logic errors before you get your application to an end user, and to detect data errors within all editions of your application.

The "-debug" switch has got absolutely nothing to do with contracts whatsoever. The "-debug" switch has identical functionality to the "-version" switch. There can be considered as aliases for each other. However, the reason for using different words ('debug' vs 'version') is to emphasize the different purposes of the conditional code. Code that is conditionally compiled in with 'version' represents valid alternatives of the application based on environmental, platform, or usage variations. Those fragments of code conditionally compiled in with 'debug' represent valid alternatives for pre-production editions. By having both 'version' and 'debug', we can intermix there usage to create very precise editions of the application to suit all purposes.

Yes, it is easy to confuse the debug() construct with contract programming, but in D they are not the same. It is especially important to realize that the "-release" switch has no effect on the debug() construct.

The "-release" switch also removes the hidden asserts (range-checking, missing returns, etc...) as well as the explicit asserts.

As the assert() call only displays information useful to people who have access to the source code, it is a bit pointless using asserts to alert end-users to problems.

-- 
Derek Parnell
Melbourne, Australia
16/08/2005 7:06:17 AM
August 15, 2005
On Mon, 15 Aug 2005 20:18:48 +0000 (UTC), AJG wrote:

> Hi,
> 
>>If you want to use boxer in a module with asserts turned on you have to recompile phobos with asserts turned on (ie without -release). Edit the makfile in dmd/src/phobos to uncomment the unittest DFLAGS variable and run make.
> 
> While this helps with std.boxer specifically, it doesn't help with contracts in general. Before anything, are the following three things clearly defined anywhere?

Yes. In the documentation for the DMD compiler and the documentation for conditional compilation.

> A) -debug
-debug
compile in debug code
-debug=level
compile in debug code <= level
-debug=ident
compile in debug code identified by ident

> B) -release
-release
compile release version, which means not generating code for contracts and
asserts

> C) -debug -release
Both the above.
> D) -release -debug (if different from C).
Same as above.

"-release" and "-debug" are totally independent from each other.

> In addition, I'm really surprised (read: annoyed) that release/debug have an effect on contracts. This is faulty logic IMHO.

"-debug" does not effect contracts at all. Only "-release" does.

> It would make more sense to do the following:
> 
> # void Foo(int a) in {
> #     assert(a == 42); // Stays there forever.
Why? What useful information would this give to the end user?

> #     debug assert(someExpensiveCheck(a)); // Removed in release.
> # } body { /* body */ }

You are encouraged to code such a 'contract' in this manner instead ...

 void Foo(int a)
 in {
    assert(someExpensiveCheck(a)); // Removed in release.
 }
 body {
    // Input *data* validation.
    if (a == 42) Abend("In Foo(), the input data must be 42");
    /* rest of body */
 }

-- 
Derek Parnell
Melbourne, Australia
16/08/2005 7:35:23 AM
August 16, 2005
Hi Derek,

>>Before anything, are the following three things clearly defined
>> anywhere?
>
>Yes. In the documentation for the DMD compiler and the documentation for conditional compilation.

Well, I must be reading something wrong, cause...

~test.d:
# void main() {
#     printf("Before\n");
#     assert(false);
#     printf("After\n");
# }

>> A) -debug
>-debug
>compile in debug code
>-debug=level
>compile in debug code <= level
>-debug=ident
>compile in debug code identified by ident

This is fine. Debug seems to work properly.

Output:
# Before
# Error: AssertError Failure test.d(3)

>> B) -release
>-release
>compile release version, which means not generating code for contracts and
>asserts

Not quite...

Output:
# Before
# Segmentation Fault

>> C) -debug -release
>Both the above.
>> D) -release -debug (if different from C).
>Same as above.

Once again, the output is:
# Before
# Segmentation Fault

>"-release" and "-debug" are totally independent from each other.

Well, sort of. What about when you don't specify _either_ one? The it is assumed you meant -debug, right? Well, then that means there is no way to _explicitly_ set NO-debug, other than to say -release. That means, thus, that they are related.

>> In addition, I'm really surprised (read: annoyed) that release/debug have an effect on contracts. This is faulty logic IMHO.
>"-debug" does not effect contracts at all. Only "-release" does.

Doesn't seem to be that way. -release makes asserts segfault.

>> It would make more sense to do the following:
>> 
>> # void Foo(int a) in {
>> #     assert(a == 42); // Stays there forever.
>Why? What useful information would this give to the end user?

It's _not_ about the user. It's about basic function safety. Why have a section called "in," where you are supposed to check for pre-conditions, when that section is effectively _useless_ in real code? This is a bad design decision, IMHO.

Asserts are a simple and elegant way to prevent bizarre and potentially catastrophic behaviour that you don't expect to happen in real code, but just _might_. When debugging, they are useful tools to the programmer. But they are doubly useful: In real code, they are last-resort, emergency guards.

Well, you say, throw an exception. You want me to instead throw an exception every time I have an assert? The sheer verbosity will kill you. For every:

assert(c);

You must use:

if (!c) throw new Exception("Error: AssertError Failure ajg.module.d(13)");

Look at that monster. If you pepper your code with Exceptions where regular asserts would have sufficed, you are looking at some serious code bloat. Just like const, the meaning is lost in all that pomposity and syntax. Assert, on the other hand is concise and elegant. Therefore, I use asserts a lot, because I would want my code to be bulletproof.

Moreover, there are even more disadvantages:

1) It's a heck of a lot more work. You are less likely to do it.
2) You lose automatic module/line-number indications.
3) It's a more complex construct.
4) Thus, you lose the immediate, quick, straight-forward meaning. An assert is a
simple guard. You see it an you know that condition must never happen.

OTOH, an exception is a much more powerful error-handling facility. When I put an assert, I don't want to handle an error, I want execution to come to a screeching halt lest the situation get even worse.

Well, use a _function_ that throws an exception, you say. I suppose that's what your "Abend" function does, right? First off, still quite verbose:

# // Assuming this:
# void assert2(int c, string m) {
#     if (!c) throw new Exception("Error: AssertError Failure " ~ m);
# }

assert(c);
vs.
assert2(c, "ajg.module.d(13)");

Even more problems:

1) It's a lot more work. Harder to maintain.
2) Still no automatic module/line-number.
3) Even worse, now the exception will seem to originate in a completely
different, generic place. Bad!
4) The compiler has no knowlege of the fact that the function is a special one,
designed specifically to throw. So it can't detect dead code. It also can't
"know" what you mean when you say assert(false).
5) Replacing a built-in _language_ facility with a hack is just ridiculous.
That's why there is assert() in the first place.

>You are encouraged to code such a 'contract' in this manner instead ...
> void Foo(int a)
> in {
>    assert(someExpensiveCheck(a)); // Removed in release.
> }
> body {
>    // Input *data* validation.
>    if (a == 42) Abend("In Foo(), the input data must be 42");
>    /* rest of body */
> }

Two things:

1) Once again, it's not only about user-input validation. It's about validation of preconditions in general. These can, for example, be parameters that can come from anywhere. They can come directly from the end user, or from another programmer, or from a corrupted stack, or from god knows where.

But it doesn't even have to be parameters. It can be any sort of precondition. Having enough memory. A thread having stopped. A variable having been set. A mutex having been released. Anything. It makes sense to put these things in a section called "in," which is specifically designed to check for pre-conditions.

You mean to say all these things magically dissapear in production code? If that's the "philosophy," then that's quite dangerous and naive. It's exactly the _other_ way around, these things become more likely to happen (uncontrolled, distinct environment(s)) and much more likely to be seriously harmful (real, important data/systems at stake).

2) Also, why bother having an "in" section in the first place? This just creates a mess. You must split your "real" checks from the fake ones into two sections, when the "in" one could nicely handle both. This split would be fine for one function, but not for all. It's very distracting.

Cheers,
--AJG (linux w/ 129).

PS: As you can tell, I am pro-assert, and pro-in. In other words, pro-safety. You must always practice safe hex, people! ;)



August 16, 2005
Derek Parnell wrote:
> On Mon, 15 Aug 2005 17:02:14 +0000 (UTC), AJG wrote:
> 
> 
>>Hi,
>>
>>First, I was happily coding in D under -debug. Then, I started using std.boxer
>>which requires that I use -release because of unresolved linking.
>>
>>So I add -release (in _addition_ to -debug) and all hell breaks lose.
>>
>>1) asserts no longer display anything meaningful; they segfault.
>>2) pre-condition (in) contracts disappear altogether.
>>
>>What's going on? This seems extremely unreasonable to me.
>>
>>I understand that some crazy people don't like safety contracts in their
>>-release code, but I specified -debug too.
>>
>>Would it be possible to restore these 2 contracts, properly (no segfault), at
>>least under -debug? Please? I'm on linux w/ 129.
> 
> 
> Believe it or not, but this is a philosophical discussion.

Why then does the overview page say:
"D (...) doesn't come with (...) an overriding philosophy."
http://www.digitalmars.com/d/overview.html

and um, I think the word "philosophy" has different meanings in different context, and in the context of your post, it means "principle" or "idea"..

so if we debate the meaning of "-release" it wouldn't really be a /philosophical/ discussion, because we're not debating the nature of time and space :P

From answers.com:
http://www.answers.com/philosophy&r=67
2. Investigation of the nature, causes, or principles of reality, knowledge, or values, based on logical reasoning rather than empirical methods.

7. A set of *ideas or beliefs* relating to a particular field or activity; an underlying theory: /an original philosophy of advertising/.


> 
> Walter's philosophy (and yes, I'm speculating here) is that the purpose of
> the in{} and out{} blocks and assert() calls is to alert the developer of
> any mistakes in their code logic. They are not to be used to detect bad
> data. The "-release" effects these constructs because by the time you
> create the production edition, all the code logic has been validated.
> 
> This means that if you require that the end user is alerted to logic
> errors, your choices are that you supply them with a non-release edition
> and/or you code your 'contracts' outside of the in{}, out{}, and assert()
> constructs. The choice is yours.
> 
> Further more, validation of user data should never be coded inside contract
> constructs as these are designed to detect *logic* mistakes and not data
> problems. In short, you are encouraged to detect logic errors before you
> get your application to an end user, and to detect data errors within all
> editions of your application.
> 
> The "-debug" switch has got absolutely nothing to do with contracts
> whatsoever. The "-debug" switch has identical functionality to the
> "-version" switch. There can be considered as aliases for each other.
> However, the reason for using different words ('debug' vs 'version') is to
> emphasize the different purposes of the conditional code. Code that is
> conditionally compiled in with 'version' represents valid alternatives of
> the application based on environmental, platform, or usage variations.
> Those fragments of code conditionally compiled in with 'debug' represent
> valid alternatives for pre-production editions. By having both 'version'
> and 'debug', we can intermix there usage to create very precise editions of
> the application to suit all purposes.
> 
> Yes, it is easy to confuse the debug() construct with contract programming,
> but in D they are not the same. It is especially important to realize that
> the "-release" switch has no effect on the debug() construct.
> 
> The "-release" switch also removes the hidden asserts (range-checking,
> missing returns, etc...) as well as the explicit asserts.
> 
> As the assert() call only displays information useful to people who have
> access to the source code, it is a bit pointless using asserts to alert
> end-users to problems.
> 
August 16, 2005
Hi,

>I agree , I think contracts should be completely seperate from 'release' and 'debug'.   Looking at the front end ( mars.c : 385 ) , it wouldn't take much at all , just an extra command line argument , -contracts or some such.

I'm glad someone agrees. Another pro-safety feller I see ;)

Indeed, a -contract argument would work well. Contracts should _always_ be enforced IMO. But I understand this isn't likely to happen. So, at least the choice to enforce them should be given independent of debug/release.

For the tuning/tweaking crowd, a more fine-grained version could be offered:

-contracts // all
-contracts:in // preconditions
-contracts:assert // asserts
etc.

>This has been talked about before , not sure what the outcome was.

Walter?

>Charlie

>P.S. Also , in the source it has useAssert parameter set to true if unittests are on , maybe try that ?

Not sure what you mean. Which source?

Cheers,
--AJG.


August 16, 2005
Hi,

>> Would it be possible to restore these 2 contracts, properly (no segfault), at least under -debug? Please? I'm on linux w/ 129.
>
>Believe it or not, but this is a philosophical discussion.

This is all well and good, but D is supposed to be borne out of practice. The current "philosophy" as it were doesn't seem very pragmatic. See below.

>Walter's philosophy (and yes, I'm speculating here) is that the purpose of the in{} and out{} blocks and assert() calls is to alert the developer of any mistakes in their code logic. They are not to be used to detect bad data. The "-release" effects these constructs because by the time you create the production edition, all the code logic has been validated.

Walter, could you confirm this? If it's true, this is not good news for safety.

>This means that if you require that the end user is alerted to logic errors, your choices are that you supply them with a non-release edition and/or you code your 'contracts' outside of the in{}, out{}, and assert() constructs. The choice is yours.

The only choice I see is between safe (debug) and unsafe(release). I understand
if you want the marginal extra speed of the unsafe version, but perhaps this
safety (aka contracts) could be made into a separate option?

"Release" code should have nothing to do with contracts or safety. It should be about removing extra symbols, stripping useless sections, etc. Not safety. Not contracts. Well, IMHO, of course.

Release is already sort-of indendent of debug. Fine. Couldn't it also be independent of contracts? This would solve a lot.

>Further more, validation of user data should never be coded inside contract constructs as these are designed to detect *logic* mistakes and not data problems. In short, you are encouraged to detect logic errors before you get your application to an end user, and to detect data errors within all editions of your application.

Could I get a precise definition of a logic mistake vs. a "data" mistake, please? I would think the two are intertwined. Thus, there is only _one_ kind of error coming into a function: a pre-condition. Everything falls into that.

The in block is _specifically_ stated to take care of pre-conditions. But it fails in -release. It leaves the code unprotected against unexpected failing pre-conditions. It's as simple as that: No pre-condition protection. No safety.

>By having both 'version'
>and 'debug', we can intermix there usage to create very precise editions of
>the application to suit all purposes.

I don't see where you are getting all that "precision," since a single -release (even with -debug(s)) wipes out all in/out contracts and causes asserts to segfault. That's kind of un-precise. Rather, it's kind of blunt.

>Yes, it is easy to confuse the debug() construct with contract programming, but in D they are not the same. It is especially important to realize that the "-release" switch has no effect on the debug() construct.

Yes, it's counter-intuitive. Traditionally, release and debug are mutually exclusive (as they should be), since they are contradicting terms. But not in D. Great. How is this a good thing?

>The "-release" switch also removes the hidden asserts (range-checking, missing returns, etc...) as well as the explicit asserts.

This is insane. So IndexOutOfBounds checks are _gone_ in release? So I guess arrays will _NEVER_ be overrun in production code, right? Because as we know, _all_ bugs are solved during the initial design. Yeah, good thinking.

>As the assert() call only displays information useful to people who have access to the source code, it is a bit pointless using asserts to alert end-users to problems.

Uh... no. A human-readable line like:

"Error: AssertError Failure ajg.module.d(13)"

is:
1) A lot friendlier nasty segfault.
2) More understandable.
3) QUITE useful. The user could actually send this message to customer support,
or when submitting a bug report, etc.

The idea that asserts (or worse, contracts in general) are only useful to the immediate programmer is misguided.

Cheers,
--AJG.



« First   ‹ Prev
1 2 3