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
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.
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 ...
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.