- "GotW #97: Assertions (Difficulty: 4/10)" by Herb Sutter - 13 Updates
- atomic<>-costs - 10 Updates
- [Jesus Loves You] Time is approaching - 1 Update
- Strange compiler warning... - 1 Update
Lynn McGuire <lynnmcguire5@gmail.com>: Jan 06 05:26PM -0600 On 1/5/2021 3:14 AM, Paavo Helde wrote: >> Wow, we do not have any asserts in our 450,000 lines of C++ code. > For comparison, we have 7708 asserts in 600,000 lines of C++ code. I > guess this depends on the project type very much. We put in extensive tests that run both in debug and release modes. BTW, my software also has 850,000 lines of Fortran code also for a total of 1.3 million lines of F77 and C++. Lynn |
David Brown <david.brown@hesbynett.no>: Jan 07 09:42AM +0100 On 06/01/2021 22:35, Scott Lurndal wrote: > static_assert is quite useful, however, in C++ code. I'd go further and say static assertions are extremely useful in C and C++ code, and have been so from long before they were added to the languages. (Prior to C11/C++11 they could be done with some ugly macros.) They have no costs at run-time, serve to document assumptions or requirements, and make code more robust. As has been noted in this thread, run-time assertions have run-time costs and open questions such as what to do when the assertion fails, and how you test the assertion (untested error handling code is not a good idea) - static assertions have no such complications. |
Ian Collins <ian-news@hotmail.com>: Jan 07 10:21PM +1300 On 07/01/2021 21:42, David Brown wrote: > as what to do when the assertion fails, and how you test the assertion > (untested error handling code is not a good idea) - static assertions > have no such complications. An effective way to test assertion failures is to have them throw an exception when running unit tests. -- Ian. |
David Brown <david.brown@hesbynett.no>: Jan 07 10:37AM +0100 On 07/01/2021 10:21, Ian Collins wrote: >> have no such complications. > An effective way to test assertion failures is to have them throw an > exception when running unit tests. But if those assertions are still in the final code, configured to do something else (log an error, restart the system, or whatever), then you are not testing the actual code. Many failures in real systems have been caused by people putting in extra checks "just to be sure" without proper verification of how those checks work and what happens if they trigger. |
Paavo Helde <myfirstname@osa.pri.ee>: Jan 07 02:35PM +0200 07.01.2021 11:37 David Brown kirjutas: > But if those assertions are still in the final code, configured to do > something else (log an error, restart the system, or whatever), then you > are not testing the actual code. Over the years I have made up my mind about assertions: these are just development and debugging aids and should not be present in released code. The same holds for other assert-like features like MSVC checked iterators. Even MS have figured it out by now, see "https://docs.microsoft.com/en-us/cpp/standard-library/checked-iterators?view=msvc-160" : "By default, the value for _ITERATOR_DEBUG_LEVEL is 0 for release builds and 2 for debug builds." YMMV, of course. > Many failures in real systems have been caused by people putting in > extra checks "just to be sure" without proper verification of how those > checks work and what happens if they trigger. Agreed. |
James Kuyper <jameskuyper@alumni.caltech.edu>: Jan 07 09:23AM -0500 On 1/7/21 7:35 AM, Paavo Helde wrote: ... > Over the years I have made up my mind about assertions: these are just > development and debugging aids and should not be present in released code. If you have such aids disabled in the released code, the code should be thoroughly tested with those aids disabled, before being released. |
Paavo Helde <myfirstname@osa.pri.ee>: Jan 07 05:37PM +0200 07.01.2021 16:23 James Kuyper kirjutas: >> development and debugging aids and should not be present in released code. > If you have such aids disabled in the released code, the code should be > thoroughly tested with those aids disabled, before being released. Not sure if you meant s/disabled/enabled/ in the last line. With "enabled" I agree of course, with "disabled" not. A non-op is a non-op, and all such aids must be non-ops if not triggered (and fixed ASAP when triggered). If some developer writes non-op asserts then it's a disciplinary problem, not a technical one. |
Paavo Helde <myfirstname@osa.pri.ee>: Jan 07 05:39PM +0200 07.01.2021 17:37 Paavo Helde kirjutas: > If some developer writes non-op asserts > then it's a disciplinary problem, not a technical one. Heh, wrote the opposite myself here, please s/non-op/non-non-op/ ;-) |
James Kuyper <jameskuyper@alumni.caltech.edu>: Jan 07 10:53AM -0500 On 1/7/21 10:37 AM, Paavo Helde wrote: >> thoroughly tested with those aids disabled, before being released. > Not sure if you meant s/disabled/enabled/ in the last line. With > "enabled" I agree of course, with "disabled" not. No, I meant disabled. You need to test the code as delivered, it may malfunction in ways that are different from the way it functions when those aids are enabled. > A non-op is a non-op, and all such aids must be non-ops if not triggered > (and fixed ASAP when triggered). Those aids should be no-ops when disabled - but assuming that they actually are no-ops is a bad idea. Among other things, their absence may affect the way that other code is optimized. |
Richard Damon <Richard@Damon-Family.org>: Jan 07 10:56AM -0500 On 1/7/21 10:37 AM, Paavo Helde wrote: > A non-op is a non-op, and all such aids must be non-ops if not triggered > (and fixed ASAP when triggered). If some developer writes non-op asserts > then it's a disciplinary problem, not a technical one. The key is that if you had the tests in place for development, you may run into an issue that removing the tests break the code. This can happen if the test have some unnoticed side effect, that omitting creates a problem. |
wij <wyniijj@gmail.com>: Jan 07 08:02AM -0800 On Wednesday, 6 January 2021 at 16:19:41 UTC+8, Paavo Helde wrote: > This probably also depends on the project type. Imagine implementing > something like JPEG compression algorithm, what are the chances a human > reviewer would notice an one-off mistake somewhere deep in the algorithm? If broken down: #define ASSERT(expr) \ // 1.executable comment (run-time check) if(!expr) { \ // cerr << #expr; \ // 2.print expr abort(); \ // 3.abort } I rarely use assert because of (2) and (3). If I am to implement a complex algorithm like JPEG compression, I would write something like: if(cond==false) { THROW(-1) // register __FILE__, __LINE__ and throw a general error } But, in general, such codes are not common ( implement complex algorithm is not a common task) |
Paavo Helde <myfirstname@osa.pri.ee>: Jan 07 08:37PM +0200 07.01.2021 17:53 James Kuyper kirjutas: > Those aids should be no-ops when disabled - but assuming that they > actually are no-ops is a bad idea. Among other things, their absence may > affect the way that other code is optimized. Just compiling in release mode will affect how the code is optimized, no need to bring debug asserts into play. And of course the final code needs to be tested (and even more than debug builds), it's just that removal of asserts is not a major or even a minor reason for that. Of course, disabling an assert may hide or obfuscate an existing bug, but I have never seen a bug *created* by disabling an assert. On the other hand I have seen multiple problems caused by over-eager asserts left in the code. I believe my rants about MSVC checked iterators can still be found in ancient c.l.c++.m archives. |
Paavo Helde <myfirstname@osa.pri.ee>: Jan 07 09:00PM +0200 07.01.2021 18:02 wij kirjutas: > } > But, in general, such codes are not common ( implement complex algorithm is > not a common task) The exact definition of the assert macro is not so important because one can always run the code in the debugger and put a breakpoint in the failure branch. But yes, our asserts throw exceptions instead of abort() as these are easier to manage. If asserts are disabled in release, then they have zero cost and one can freely use them also in non-complex code, to protect against typos, copy-paste errors, etc. For example, just today I wrote: std::string src = /*...*/; // add zero padding; leave room for 16-byte MD5 hash. unsigned int k = (src.length()+16) % enc.MandatoryBlockSize(); if (k!=0) { k = enc.MandatoryBlockSize() - k; } src.resize(src.length()+16+k); DEBUG_ASSERT(src.length() >= 16); DEBUG_ASSERT(src.length() % enc.MandatoryBlockSize() == 0); Silly asserts (esp the 1st), but I feel more confident I have not mistyped anything, and that if I change something in the future there are less chances I screw it up. The asserts also document the needed preconditions for next lines. |
Bonita Montero <Bonita.Montero@gmail.com>: Jan 07 08:17AM +0100 > One other nitpick... Make sure that your: > atomic<uint64_t> atomicValue; > Is isolated: Aligned and padded on a cache line boundary. That's automatically done through the /-8-alignment of the compiler. |
Bonita Montero <Bonita.Montero@gmail.com>: Jan 07 09:04AM +0100 The XCHG-loop was incorrect: #if defined(_MSC_VER) #include <Windows.h>
Subscribe to:
Post Comments (Atom)
|
No comments:
Post a Comment