Re: [boost] suggestion on assertion macros

there were a discussion recentrly about verifying arguments of assertion macros while checks are turned off
i've got an idea of how to check the argument(s) and guarantee zero code size and runtime overhead
Hi, This is a good addition to assertions, but once we decide that we are improving assertions, there is much more that needs an improvement. Most of them are listed in the thread on Contract++ library (proposed for Boost) that you are already referring to. But let me list the potential improvements here. 1. If the expression in assertion throws an exxception, this should also be considered an assertion failure. Otherwise evaluating or not evaluating an assertion may render different program behavior. You can implement that by wrapping the expression with a try-catch block; but then assertion is a statement rather than an expression. Personally I think it is even better that an assert in a statement and it cannot be a subexpression of a bigger expression, but it no longer complies to assertion interface. Lambdas have the capability of changing statements into expressions, but we do not have them yet. 2. Be able to disable some assertions, but not all, e.g. I want the following assert in my code never to execute: assert<low_level>( is_sorted( v.begin(), v.end() ) ); find_logarithmic( v.begin(), v.end(), val ); Simply because it may be too slow even in debug. 3. I may want to disable even syntax checking in order for my compilation to run faster. I guess we should also consider user that prefer slower applications that compile faster 4. Make sure that the expression does not access any global variables. Well, we shouldn't really forbid that but give it as an option for the programmers that like "functional style" programming. I don't know how to do that now, but with lambdas, I believe it is posible with empty capture lists. 5. At least try to limit the possibility of the expression having any side effect. Contract++ ttries to do it by enforcing the const correctness of some inputs. Perhaps, even the old assert is left alone and some super-assert like the one from Concept++ should be incorporated into Boost and be the preferred way of veryfing user assumptions. Regards, &rzej

On Sat, Mar 13, 2010 at 2:43 AM, Andrzej Krzemienski <akrzemi1@gmail.com> wrote:
This is a good addition to assertions, but once we decide that we are improving assertions, there is much more that needs an improvement. Most of them are listed in the thread on Contract++ library (proposed for Boost) that you are already referring to. But let me list the potential improvements here.
Why don't we leave assertions alone? Anything you do to "improve" them makes them more tolerable which makes them something other than assertions. Assertions should print a message and exit. OK a smack to the head would also be an improvement but that's about as far as I'd go. :) Emil Dotchevski Reverge Studios, Inc. http://www.revergestudios.com/reblog/index.php?n=ReCode

Emil Dotchevski wrote:
On Sat, Mar 13, 2010 at 2:43 AM, Andrzej Krzemienski <akrzemi1@gmail.com> wrote:
This is a good addition to assertions, but once we decide that we are improving assertions, there is much more that needs an improvement. Most of them are listed in the thread on Contract++ library (proposed for Boost) that you are already referring to. But let me list the potential improvements here.
Why don't we leave assertions alone? Anything you do to "improve" them makes them more tolerable which makes them something other than assertions.
Assertions should print a message and exit.
Well said. The idea of "Be able to disable some assertions, " sounds especially weird. Assertions are not for purpose of logging and such. Categories of assertions severity make little sense to me. Best regards, -- Mateusz Loskot, http://mateusz.loskot.net Charter Member of OSGeo, http://osgeo.org

Mateusz Loskot wrote:
Emil Dotchevski wrote:
On Sat, Mar 13, 2010 at 2:43 AM, Andrzej Krzemienski <akrzemi1@gmail.com> wrote:
This is a good addition to assertions, but once we decide that we are improving assertions, there is much more that needs an improvement. Most of them are listed in the thread on Contract++ library (proposed for Boost) that you are already referring to. But let me list the potential improvements here.
Why don't we leave assertions alone? Anything you do to "improve" them makes them more tolerable which makes them something other than assertions.
Assertions should print a message and exit.
Well said.
The idea of "Be able to disable some assertions, " sounds especially weird. Assertions are not for purpose of logging and such. Categories of assertions severity make little sense to me.
Best regards,
I couldn't agree more, but removing the compile time warning in cases like the following does not change the nature of assertions. void my_method(const int& my_param) { assert(my_param); } Currently I get compiler warnings about my_param being unused when compiling with NDEBUG defined. I'd be glad to get rid of them. And I certainly do not want to have my code sprinkled with #ifdef NDEBUG void my_method(const int&) #else void my_method(const int& my_param) #endif { assert(my_param); } Regards, Roland

Roland Bock wrote:
Mateusz Loskot wrote:
Emil Dotchevski wrote:
On Sat, Mar 13, 2010 at 2:43 AM, Andrzej Krzemienski <akrzemi1@gmail.com> wrote:
This is a good addition to assertions, but once we decide that we are improving assertions, there is much more that needs an improvement. Most of them are listed in the thread on Contract++ library (proposed for Boost) that you are already referring to. But let me list the potential improvements here.
Why don't we leave assertions alone? Anything you do to "improve" them makes them more tolerable which makes them something other than assertions.
Assertions should print a message and exit.
Well said.
The idea of "Be able to disable some assertions, " sounds especially weird. Assertions are not for purpose of logging and such. Categories of assertions severity make little sense to me.
Best regards,
I couldn't agree more, but removing the compile time warning in cases like the following does not change the nature of assertions.
void my_method(const int& my_param) { assert(my_param); }
Currently I get compiler warnings about my_param being unused when compiling with NDEBUG defined.
Yes, that is a problem though of different nature than categories of assertions.
I'd be glad to get rid of them. And I certainly do not want to have my code sprinkled with
#ifdef NDEBUG void my_method(const int&) #else void my_method(const int& my_param) #endif { assert(my_param); }
AFAIK, this is an issue of particular implementation you use. The assert macro from GNU C Library wraps its argument cast to void if NDEBUG is defined. No warning is issued. Best regards, -- Mateusz Loskot, http://mateusz.loskot.net Charter Member of OSGeo, http://osgeo.org

Mateusz Loskot wrote:
Currently I get compiler warnings about my_param being unused when compiling with NDEBUG defined.
Yes, that is a problem though of different nature than categories of assertions.
I'd be glad to get rid of them. And I certainly do not want to have my code sprinkled with
#ifdef NDEBUG void my_method(const int&) #else void my_method(const int& my_param) #endif { assert(my_param); }
AFAIK, this is an issue of particular implementation you use. The assert macro from GNU C Library wraps its argument cast to void if NDEBUG is defined. No warning is issued.
Best regards,
Hmm. I use gcc (4.2.4) and I get the warning (-Wall -Wextra). That's why I proposed that code in the other part of this discussion (with great help from Peter and Steven): #include <cassert> #ifdef NDEBUG #ifdef assert #undef assert #define assert(cond) static_cast<void>(sizeof(cond? 0: 0)); #endif #endif int main() { int i = 0; assert(i); } This way, I get no warning about variable i being unused, it is even being made sure that the condition for the assertion is verifiable and still the code results in nothing if NDEBUG is defined. I plan on using that myself. I think it would be useful for others, too. Regards, Roland

Roland Bock wrote:
Mateusz Loskot wrote:
Currently I get compiler warnings about my_param being unused when compiling with NDEBUG defined.
Yes, that is a problem though of different nature than categories of assertions.
I'd be glad to get rid of them. And I certainly do not want to have my code sprinkled with
#ifdef NDEBUG void my_method(const int&) #else void my_method(const int& my_param) #endif { assert(my_param); }
AFAIK, this is an issue of particular implementation you use. The assert macro from GNU C Library wraps its argument cast to void if NDEBUG is defined. No warning is issued.
Best regards,
Hmm. I use gcc (4.2.4) and I get the warning (-Wall -Wextra).
I forgotten about -Wextra option and now GCC 4.4.1 reports the same worning, indeed. I was wrong, the assert macro is not that clever as I suggested $ g++ -E -pedantic -Wall -Wextra -DNDEBUG test.cpp int main() { int* p = 0; (static_cast<void> (0)); // assert macro } $ g++ -pedantic -Wall -Wextra -DNDEBUG test.cpp test.cpp: In function ‘int main()’: test.cpp:4: warning: unused variable ‘p’ Best regards, -- Mateusz Loskot, http://mateusz.loskot.net Charter Member of OSGeo, http://osgeo.org

Mateusz Loskot wrote: [snip]
I forgotten about -Wextra option and now GCC 4.4.1 reports the same worning, indeed. I was wrong, the assert macro is not that clever as I suggested
$ g++ -E -pedantic -Wall -Wextra -DNDEBUG test.cpp int main() { int* p = 0; (static_cast<void> (0)); // assert macro }
$ g++ -pedantic -Wall -Wextra -DNDEBUG test.cpp test.cpp: In function ‘int main()’: test.cpp:4: warning: unused variable ‘p’
Best regards,
So what do you think of my re-definition?

Roland Bock wrote:
Mateusz Loskot wrote: [snip]
I forgotten about -Wextra option and now GCC 4.4.1 reports the same worning, indeed. I was wrong, the assert macro is not that clever as I suggested
$ g++ -E -pedantic -Wall -Wextra -DNDEBUG test.cpp int main() { int* p = 0; (static_cast<void> (0)); // assert macro }
$ g++ -pedantic -Wall -Wextra -DNDEBUG test.cpp test.cpp: In function ‘int main()’: test.cpp:4: warning: unused variable ‘p’
So what do you think of my re-definition?
It's OK, but personally I would not redefine the assert macro, but define it as a new enhanced macro for use in my project #define MYLIB_ASSERT(cond) Best regards, -- Mateusz Loskot, http://mateusz.loskot.net Charter Member of OSGeo, http://osgeo.org

Mateusz Loskot wrote:
Roland Bock wrote:
Mateusz Loskot wrote: [snip]
I forgotten about -Wextra option and now GCC 4.4.1 reports the same worning, indeed. I was wrong, the assert macro is not that clever as I suggested
$ g++ -E -pedantic -Wall -Wextra -DNDEBUG test.cpp int main() { int* p = 0; (static_cast<void> (0)); // assert macro }
$ g++ -pedantic -Wall -Wextra -DNDEBUG test.cpp test.cpp: In function ‘int main()’: test.cpp:4: warning: unused variable ‘p’
So what do you think of my re-definition?
It's OK, but personally I would not redefine the assert macro, but define it as a new enhanced macro for use in my project
#define MYLIB_ASSERT(cond)
Best regards,
You're right, re-definition is bound to lead to confusion. Regards, Roland

Mateusz Loskot wrote:
I forgotten about -Wextra option and now GCC 4.4.1 reports the same worning, indeed. I was wrong, the assert macro is not that clever as I suggested
Which is not quite surprising as the C standard says this: <quote> If NDEBUG is defined as a macro name at the point in the source file where <assert.h> is included, the assert macro is defined simply as #define assert(ignore) ((void)0) </quote> Gevorg

Hello all, I have listed a few questions below. ASSUMPTION: Assertions should be used to document, program, and check software specifications. (*) On Sat, Mar 13, 2010 at 3:34 PM, Emil Dotchevski <emildotchevski@gmail.com> wrote:
Why don't we leave assertions alone? Anything you do to "improve" them makes them more tolerable which makes them something other than assertions.
All assertion "improvements" listed by Andrzej together with Contract Programming invariants, preconditions, postconditions, and subcontracting aim to better serve the assertion purpose (*) of programming software specs. These improvements are taken and elaborated from [Meyer1997], [Crowl2006] (all previous revisions of this proposal are also relevant), and even [Stroustrup1997] (see http://dbcpp.sourceforge.net/contract__/bibliography.html for a list of the [xyz] references I am using in this email). For example, [Crowl2006] shows how most of the std::vector specs can be programmed using the Contract Programming assertion improvements. Now, if we were to leave C-style assertions alone, without improving them, then we would not be able to program the std::vector specs -- would we? Furthermore: 1) Which one of these assertion "improvements" makes assertions "more tolerable"? Why and how? 2) Tolerable to what? On Sat, Mar 13, 2010 at 3:34 PM, Emil Dotchevski <emildotchevski@gmail.com> wrote:
Assertions should print a message and exit. OK a smack to the head would also be an improvement but that's about as far as I'd go. :)
Indeed, by default, the Contract Programming "improvements" discussed above print a message and then they std::terminate() (no exit(), nor abort(), nor throw). (None of these "improvements" smack programmers yet and I am thankful of that because I know I will keep making coding errors :)) .) On Sat, Mar 13, 2010 at 5:21 PM, Mateusz Loskot <mateusz@loskot.net> wrote:
Well said. The idea of "Be able to disable some assertions, " sounds especially weird. Assertions are not for purpose of logging and such. Categories of assertions severity make little sense to me.
As Andrzej explained, there is a specific use case for "disabling some assertions" and it has to do with the computational complexity of the assertion check. For example, assertions can be used to program the following specs: (a) "After vector::push_back(x), x should appear at the back of the vector". (b) And also "after vector::push_back(x), no other vector element, but the newly added x, has changed". These conditions both assert software specs so they are within the stated purpose for assertions (*). As explained for example in [Mitchell2002] (or better yet by most AI books), (b) uses assertions to program "frame conditions". Frame conditions are notoriously computationally expensive to check: In this example (a) can be checked in O(1) while the frame condition (b) will run in O(n) (where n is the size of the vector). Therefore, "categories of assertion severity" (or to use a better term "assertion importance ordering" as mentioned in [Crowl2005]) could be used to tag frame conditions with a different importance level so to disable frame condition assertions while keeping the other assertions for the sake of efficiency. 4) What does this "assertion importance ordering" use case have to do with "logging and such"? (I think it has nothing to do with logging and all to do with the computational complexity of the assertion check...) In my opinion: i) The improvement suggested in this email thread to disable compilation of the C-style assert() based on NDEBUG is relevant in the context of selectively disabling assertion compilation and checking (I might actually use it in my Contract++ library for the CONTRACT_BLOCK_INVARIANT() macro). ii) However, for an OO language like C++, this one improvement should be considered within the broader list of assertion improvements indicated by Andrzej and captured by Contract Programming so to more comprehensively serve (*). Regards, Lorenzo
participants (6)
-
Andrzej Krzemienski
-
Emil Dotchevski
-
Gevorg Voskanyan
-
Lorenzo Caminiti
-
Mateusz Loskot
-
Roland Bock