-
October 12th, 2012, 06:05 AM
#1
Validate unsigned operations?
Hello,
I don't know if this is a common problem, but I've sometimes encountered unexpected runtime issues caused by unsigned values being decremented below zero.
Example 1: "unsigned_value += negative_integer_value;"
Example 2: "for( size_t i = size - 1; i >= 0; --i )"
My compiler doesn't provide any compile-time or run-time warnings.
As far as I know, it's not possible to overload operators of primitive data types to check if the unsigned value is decremented below zero.
Do you know of any clever strategy to trace such cases at debug runtime, without having to add asserts all over the code? It's important that it does not affect performance in release mode.
-
October 12th, 2012, 06:09 AM
#2
Re: Validate unsigned operations?
Decrementing an unsigned integer that is zero is well defined and not necessarily a mistake. The solution, methinks, is to write tests to check that your code is doing what you intend.
-
October 12th, 2012, 06:24 AM
#3
Re: Validate unsigned operations?
Yes, it's legal, but I can't recall that I have ever done it on purpose. Maybe that behaviour is defined just because it's better than the alternative of undefined behaviour?
Writing unit tests is a good recommendation though :-)
-
October 12th, 2012, 08:00 AM
#4
Re: Validate unsigned operations?
Originally Posted by TubularX
I don't know if this is a common problem, but I've sometimes encountered unexpected runtime issues caused by unsigned values being decremented below zero.
Example 1: "unsigned_value += negative_integer_value;"
Example 2: "for( size_t i = size - 1; i >= 0; --i )"
My compiler doesn't provide any compile-time or run-time warnings.
Of course not, it also doesn't flag integer division or using ++i when you actually meant --i. The compiler has a lot of tricks up its sleeve, but it cannot peak inside your head; it does not know what you want your code to do. If the result of an operation can be a negative number, then don't use unsigned integers for it; or rewrite the code such that the result cannot be negative.
Cheers, D Drmmr
Please put [code][/code] tags around your code to preserve indentation and make it more readable.
As long as man ascribes to himself what is merely a posibility, he will not work for the attainment of it. - P. D. Ouspensky
-
October 12th, 2012, 10:31 AM
#5
Re: Validate unsigned operations?
VisualStudio 2010 issues a "warning C4296: '>=' : expression is always true" when the warning level is set to /Wall. However, this level is quite a pain as a lot of headers that come with the compiler are candidates for warnings as well.
I could not get my g++ (4.6.1) to issue any warning.
Cppcheck (http://cppcheck.sourceforge.net/), a tool for static analysis, issues a warning. This tool is very useful, I use it regularly in my projects.
HTH,
Richard
-
October 12th, 2012, 12:02 PM
#6
Re: Validate unsigned operations?
if you have code where such examples are very common and unavoidable an alternative to asserts could be to replace the unsigned type with a runtime checked size_t-like type in debug builds only. You can use boost operator library to ease the writing of such a custom numeric type, adding internal asserts where needed protecting you against underflow.
That said, this solution would bring its own set of issues, like properly controlling implicit conversions to mantain consistency with the relase build behavior.
However, it may be the way to go if asserts become excessive; indeed, note that asserts ( and tests ) may contain errors themselves, so you should avoid code duplication and favour incapsulation in the same way you do with the rest of the code ...
-
October 12th, 2012, 01:56 PM
#7
Re: Validate unsigned operations?
Originally Posted by TubularX
Do you know of any clever strategy to trace such cases at debug runtime, without having to add asserts all over the code? It's important that it does not affect performance in release mode.
You could systematically seek higher level language constructs. For example instead of integer counters in for-loops you can use iterators, or the new for-each loop in C++ 11, or BOOST_FOREACH/BOOST_REVERSE_FOREACH. The Boost way is my favourite. You can easily, safely and quickly loop over every standard data structure.
Start programming at a higher abstraction level and avoid low level fiddling. It's not as efficient as one might think and it's error-prone. Seek the highest abstraction level that's reasonable and optimize only when necessary at proven bottlenecks.
Last edited by nuzzle; October 12th, 2012 at 03:23 PM.
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|