I don't doubt the need to check for division by zero. I've never heard of checking for division by negative one though!
if( *y == 0 )
return 0; //undefined
else
return *x / *y;
x, y are pointers to int32_t, I include this detail in case of relevance.
At runtime, if *x==0x80000000, *y==0xffffffff, I get the error (in Xcode):
EXC_ARITHMETIC (code=EXC_I386_DIV, subcode=0x0)
All I can find online is suggestions that it is division by zero, but as you can see from the check above, and I can see from the debug window, that is not the case here.
What does the error mean, and how can I fix it?
2's complement representation is asymmetric: there is one more negative number than positive number, and that negative number has no positive counterpart. Consequently, negating MIN_INT is an integer overflow (where MIN_INT is the value whose only 1-bit is the sign bit, 0x80000000 for 32-bit integers).
MIN_INT / -1 is, therefore, also an arithmetic overflow. Unlike overflow from subtraction (which is rarely checked), overflow when dividing can cause a trap, and apparently that's what is happening in your case.
And, yes, technically speaking you should check for the MIN_INT / -1 overflow case before dividing, because the result is undefined.
Note: In the common case of Intel x64 architecture, division overflow does trap, exactly the same as division by 0. Confusingly, the corresponding Posix signal is SIGFPE which is normally thought of as "Floating Point Exception", although there is no floating point in sight. The current Posix standard actually glosses SIGFPE as meaning "Erroneous Arithmetic Operation".
Related
I am having an issue for MISRA standards regarding wraparound error. I have tried to resolve it by having a look at options available on internet but remained unable to resolve it as remained unable to find some viable solution.
I am providing a simple example to explain my situation.
I am having a wraparound error in result line due to MISRA standards. Wraparound in unsigned arithmetic operation.
Can someone provide me a reason why it is happening and how to cater this situation.
Thanks a lot.
unsigned int x;
unsigned int y;
unsigned int z;
unsigned int result;
x= 0;
y = 60;
z = 60;
result = x-y +z;
As Dietrich Epp remarked correctly, the code analyzer observes that for the given values — which are known and visible at compile time — the sub-expression x-y will mathematically be negative. Negative values are out of the value range of unsigned types, they cannot be represented; such a situation is called an overflow. It is well-defined for unsigned integers in C++ (6.7.1/4 plus footnote 45 in the standard draft n4713) and in C (6.2.5/9 in the standard draft n1256): "Unsigned integers shall obey the laws of arithmetic modulo 2n where n is the number of bits in the value representation."
Modulo arithmetic "wraps around". One can image the possible values as a circle where the maximum (all bits set) and minimum (no bit set) values are adjacent. Like with all other adjacent values I can go from one to the other by adding or subtracting 1: ((uint8_t)0xff+1 == 0, and correspondingly ((uint8_t)0-1 == 0xff. (The bit pattern 0xff... to represent -1 in the usual 2-complement is known to most programmers, but it may still come as a surprise when it results from a computation.) In a 2-complement representation this transition comes naturally because 0xfff... +1 is 0x10000..., with the carry bit, the leading 1, "to the left" of the bits in the machine representation; it is simply thrown away.
The bottom line is: Perhaps surprisingly a small negative value like -60 assigned to an unsigned int results in a large number. This is what MISRA alerts you of.
In your particular case, with the values given, there is no issue because in modulo arithmetic addition is still the inverse operation to subtraction no matter the values so that 0-60+60 is 0. But problems may arise if z is, say, 58, so the result is -2; this would result in the second-highest value assigned to result which its type can hold. That may have disastrous consequences if e.g. the value is used to terminate a for loop. With signed integers the loop would be skipped; with unsigned integers it will, probably wrongly, run for a long time.
After clarifying the underlying issue the following questions arise:
As demonstrated the computation is well defined with unsigned operands and, with the given arguments, has an unsurprising result. Are you happy with all results which can occur with all possible argument values and combinations — that is, are you are happy with modulo arithmetic?
1a. Yes: Then the question is whether you want or must prevent the warning. Technically, there is nothing to do. Any change would likely obscure matters. Apparently, MISRA warnings can be suppressed.
1b. If that is not possible or desired your software development process will likely have a mechanism to qualify such warnings as acceptable.
1c. If that is not possible or desired you'll have to (unnecessarily) complicate your code. One solution is to simply perform the computation with 64 bit signed integers which are guaranteed to be able to hold all 32 bit unsigned values (assuming that sizeof int == 32 on your system), and assign the result with an explicit cast to indicate that the possible overflow and loss of information is intentional.
Or, if in your data y < z && x + z < UINT_MAX always holds, you can simply re-order the evaluation to result = x + z - y;, never encountering negative values in sub-expressions.
If you are unhappy with modulo arithmetic, especially with the possibility of unexpectedly large results, you have to step back and reconsider the data model you are using for your real-world data. Maybe you must qualify your data and prevent negative outcomes, or you must use signed integers, or something else is amiss.
I am learning C++ by reading Stroustrup's "Principles and Practice Using C++".
In the section about pre- and post-conditions there is the following example of function:
int area(int length, int width)
// calculate area of a rectangle;
// pre-conditions: length and width are positive
// post-condition: returns a positive value that is the area
{
if (length<=0 || width <=0)
error("area() pre-condition");
int a = length*width;
if (a<=0)
error("area() post-condition");
return a;
}
What confused me is the task about this code:
Find a pair of values so that the pre-condition of this version of
area holds, but the post-condition doesn’t.
Are there such possible values for integer that pre-conditions is ok but post-condition not?
Are there such possible values for integer that pre-conditions is ok but post-condition not?
Yes there's a number of input values, that can cause the post condition to fail. If e.g.
int a = length*width;
overflows the positive int range (std::numeric_limits<int>::max()) and the compiler implementation yields a negative value for this case.
As others noted in their answers, the situation that length*width goes out of bounds from ]0-std::numeric_limits<int>::max()[ is actually undefined behavior, and the post condition renders merely useless, because any value might need to be expected for a.
The key point to fix this, is given in #Deduplicator's answer, the pre-condition needs to be improved.
As a lance for Bjarne Stroustrup's reasonings to give that example:
I assume he wanted to point out that such undefined behavior might lead to unexpected negative values in the post-condition and surprising results for a naive assumption checked with the pre-condition.
No, there aren't any values that will, within the bounds of defined behavior of standard C++, violate the post-condition. However, there are values that still can make the function behave incorrectly, namely values so large that their product does not fit within an integer. Try passing 200'000 and 15'000.
Due to the way most compilers implement C++, you might see the post-condition being violated, but what you're actually observing is undefined behavior due to integer overflow.
The answer is that his precondition-check is incomplete. Even though it is too restrictive.
He failed to include a check that the product can be represented instead of resulting in UB:
int area(int length, int width) {
// calculate area of a rectangle
assert(length >= 0 && width >= 0 && (!width
|| std::numeric_limits<int>::max() / width >= length));
int a = length * width;
assert(a >= 0); // Not strictly neccessary - the math is easy enough
return a;
}
What comes to my mind is a signed overflow. It is undefined behavior but might yield a negative value.
Try std::numeric_limits<int>::max() and 2.
Yes if suppose you are using 16 bit computer so int = 2B Max value +32767 so in following
{
length = 500, width = 100;
if (length<=0 || width <=0) error("area() pre-condition");
int a = length*width; // a = 500 * 100 = 50000
if (a<=0) error("area() post-condition");
return a;
}
now final value will be a = -17233 because it gets into -ve value.
so second condition gets false.
Its all depends on range.
INT_MAX will fail to fulfill the post-condition when used for both length and width for all conforming compilers.
One might be tempted to say that, since the standard guarantees that INT_MAX>=32767, then INT_MAX*INT_MAX will always be greater than INT_MAX and thus not representable in an int which is defined as being able to hold a maximun value of INT_MAX.
It is a good argument and it is actually what happens most often, you will get an overflow with most compilers.
But to cover all bases we need to be aware that the C++ standard states :
3.4.3
1 undefined behavior
behavior,upon use of a nonportable or erroneous program construct or of erroneous data,for which this International Standard imposes no requirements
2 NOTE Possible undefined behavior ranges from ignoring the situation completely with unpredictable results, to behaving during translation or program execution in a documented manner characteristic of the environment
(with or without the issuance of a diagnostic message), to terminating a translation or execution (with the issuance of a diagnostic message).
3 EXAMPLE An example of undefined behavior is the behavior on integer overflow.
So it is a bit more serious than not getting the right value for the area. When INT_MAX is used for both length and width (or any other combination with a result which is not representable) there is no guarantee of what the compiled program will do. Anything can happen; from the likely ones like overflows or crashes to the unlikely ones like disk formats.
Multiplication of values that overflow the bit representation of value type is undefined because the number of bits overflowed could be more than 1. Thus you could end up with a positive or negative sign bit and the number of lost bits is variable.
Example 1: INT_MAX * 2 : result is correct but since the high bit represents the sign bit it is not corrected represented for its type.
Example 2: INT_MAX * 4 : 1 bit is lost to overflow and the the sign bit is incorrect like in the previous example.
Example 3: (INT_MAX + 1) * 2 = 0 : due to overflow of all set bits but sign is correct.
I am using a 8 bit binary representation to make it easier to read, to show why this happens.
0111 1111 // Max positive signed value
+1
1000 0000 // Sign bit set but binary value is correct
*2
0000 0000 // Upper bit is lost due to overflow
In this case there is both soft overflow, no lost information but the representation is incorrect. And hard overflow where the bit is no longer present in the result.
The difference in the overflows is how the overflow can be detected. Typically hard overflows will be detected by the hardware and require very little work for the software to handle. However software overflows may require the software to explicitly test for the overflow condition because the hardware typically does not recognize a sign bit in integer math operations.
How the run-time library handles the overflow is up to the library. Most will ignore it because it is faster to do so, while others may throw an error.
Undefined behavior does not mean it might format your disk. The result of a math operation does not alter the flow of code in any way except as the logic of the code dictates. It can ignore the overflow or try to handle it in some way. The standard does not dictate what method to employ if the code or the hardware tries to handle the problem.
Basically three there are 3 possible things that can happen.
1. The overflow is ignore and the returned value in invalid.
2. The overflow is ignored by the run-time library but the hardware throws an error that is also ignored, resulting in a hard failure of the running code. In this situation it is completely up to the OS to determine what happens next. Going nuts and destroying data would to a poor design decision.
3. The overflow is handled by the run-time library which must determine the best way to proceed. Typically this means giving the code a chance to catch the error and handle it, or by shutting down the code as graceful as possible.
Since C++11 there is a boolean value you can test:
std::numeric_limits<int>::is_modulo
If this value is true then signed arithmetic behaves in a wraparound fashion, and there is no undefined behaviour in the original code. A negative value could indeed be produced and so the test in the original code is meaningful.
For further discussion of is_modulo see here
So basically, positive values in multiplication ... result in Positive values but these may not actually fit the result type .
Your precondition is not complete, and you postcondition is also invalid. Not only you can get negative values but also positive values that are just smaller than the input value, all you need is sufficiently large values as input such that the wrap around goes beyond zero, i.e. a long-wrap-around .
You can use this :
bool multiplication_is_safe(uint32_t a, uint32_t b) {
size_t a_bits=highestOneBitPosition(a), b_bits=highestOneBitPosition(b);
return (a_bits+b_bits<=32);
}
to guard against overflow, but then you would want to employ additional checks for FALSE-Positives .
Alternatively if performance is not that much of an issue you can use MPZ library. If performance is an issue and you want to write assembly for a CPU that has an overflow flag, then you can do just that. It is possible that your compiler also can do the checks for you e.g. G++ has fno-strict-overflow or maybe cast to unsigned int after the precondition check.
At any rate, most of these solutions do not actually solve your problem that results will be foo, that is that you might get smaller area than the actual result.
So your only safe choice is to allow only safe multiplications as shown herein, doing that you miss something, but not that much.
I know that division by zero is not allowed in math, but can I use modulo by zero and what answer should I get?
For example
10%0 = ?
5%0 = ?
The standard defines it as "undefined".
In nearly all processors, the modulo is performed by the same functionality as divide. In modern larger processors, it's an instruction (x86 for example). Most often, this instruction will cause a trap when dividing by zero, and this applies whether the code is "intending to use the modulo" or "quotient" part.
It is undefined so that processors and compilers have the freedom to implement what they fancy - e.g. if the processor just returns whatever came in as the input, that's also allowed, or if it causes the entire OS to crash, that's "fine" too by the standard.
In summary, modulo of zero is just as bad as divide by zero.
(Note that typically, floating point divide by zero does NOT trap [by default], and produces a infinity value, except if the value divided is also zero, in which case you get "not a number")
In C/C++ it is Undefined behaviour, you can get various of results depending on compiler or even different instances of same program.
C11dr §6.5.5
The binary / operator yields the quotient, and the binary % operator
yields the remainder from the division of the first expression by the
second. If the second operand of / or % is zero the behavior is
undefined
The result is UB
C11dr §6.5.5 "The result of the / operator is the quotient from the division of the first operand by the second; the result of the % operator is the remainder. In both operations, if the value of the second operand is zero, the behavior is undefined."
Mathematically speaking you should get infinite, which is the correct answer... programmatically any sane compiler will warn you of division by zero as internally the modulo operator (at least in C/C++) is translated in a division (in most implementations). So the answer to your question is that you would get a floating point exception, in both cases.
After performing a mathematical operation, for say, multiplying two integers, is it possible to access the overflow flag register in a CPU with C++ ? If not what are other fast ways to check for an overflow ?
No, generally it's impossible. Some CPUs don't even have such a flag (e.g. MIPS).
The link provided in one of the comments will give you ideas on how you can do overflow checks.
Remember that in C and C++ signed integer overflows cause undefined behavior and legally you cannot perform overflow checks after the fact. You either need to use unsigned arithmetic or do the checks before arithmetic operations.
I recommend this reading in every appropriate case. From Optimizing software in C++ -
Integer overflow is another security problem. The official C standard
says that the behavior of signed integers in case of overflow is
"undefined". This allows the compiler to ignore overflow or assume
that it doesn't occur. In the case of the Gnu compiler, the assumption
that signed integer overflow doesn't occur has the unfortunate
consequence that it allows the compiler to optimize away an overflow
check. There are a number of possible remedies against this problem:
(1) check for overflow before it occurs, (2) use unsigned integers -
they are guaranteed to wrap around, (3) trap integer overflow with the
option -ftrapv, but this is extremely inefficient, (4) get a compiler
warning for such optimizations with option
-Wstrict-overflow=2, or (5) make the overflow behavior well-defined with option
-fwrapv or -fno-strict-overflow.
You'd have to do the operation and check the overflow bit in inline assembly. You could do that and jump to a label on overflow, or (more generally but less efficiently) set a variable if it overflowed.
No. Best approach to check in advance as here
If not what are other fast ways to check for an overflow ?
If you need to test after operation you can use floating point representation (double precision) - every 32-bit integer can be represented exactly as floating point number.
If all of the machines you target support IEEE (which is probably the case if you don't have to consider mainframes), you can just do the operations, then use isfinite or isinf on the results.
Fast (in terms of programmer's efforts) way is: The IEEE Standard for Floating-Point Arithmetic (IEEE 754) defines five exceptions, each of which returns a default value and has a corresponding status flag that (except in certain cases of underflow) is raised when the exception occurs.
The five possible exceptions are:
Invalid operation: mathematically undefined, e.g., the square root of a negative number. By default, returns qNaN.
Division by zero: an operation on finite operands gives an exact infinite result, e.g., 1/0 or log(0). By default, returns ±infinity.
Overflow: a result is too large to be represented correctly (i.e., its exponent with an unbounded exponent range would be larger than emax). By default, returns ±infinity for the round-to-nearest modes (and follows the rounding rules for the directed rounding modes).
Underflow: a result is very small (outside the normal range) and is inexact. By default, returns a subnormal or zero (following the rounding rules).
Inexact: the exact (i.e., unrounded) result is not representable exactly. By default, returns the correctly rounded result.
This is probably not what you want to do for two reasons:
not every CPU has an overflow flag
using C++ there is actually no way to access the overflow flag
the overflow checking tips that people have posted before might be useful.
if you really want to very write fast code that multiplies two integers and checks the overflow flag, you will have to use assembly. if you want some examples for x86, then do ask
I have a few questions about divide overflow errors on x86 or x86_64 architecture. Lately I've been reading about integer overflows. Usually, when an arithmetic operation results in an integer overflow, the carry bit or overflow bit in the FLAGS register is set. But apparently, according to this article, overflows resulting from division operations don't set the overflow bit, but rather trigger a hardware exception, similar to when you divide by zero.
Now, integer overflows resulting from division are a lot more rare than say, multiplication. There's only a few ways to even trigger a division overflow. One way would be to do something like:
int16_t a = -32768;
int16_t b = -1;
int16_t c = a / b;
In this case, due to the two's complement representation of signed integers, you can't represent positive 32768 in a signed 16-bit integer, so the division operation overflows, resulting in the erroneous value of -32768.
A few questions:
1) Contrary to what this article says, the above did NOT cause a hardware exception. I'm using an x86_64 machine running Linux, and when I divide by zero the program terminates with a Floating point exception. But when I cause a division overflow, the program continues as usual, silently ignoring the erroneous quotient. So why doesn't this cause a hardware exception?
2) Why are division errors treated so severely by the hardware, as opposed to other arithmetic overflows? Why should a multiplication overflow (which is much more likely to accidentally occur) be silently ignored by the hardware, but a division overflow is supposed to trigger a fatal interrupt?
=========== EDIT ==============
Okay, thanks everyone for the responses. I've gotten responses saying basically that the above 16-bit integer division shouldn't cause a hardware fault because the quotient is still less than the register size. I don't understand this. In this case, the register storing the quotient is 16-bit - which is too small to store signed positive 32768. So why isn't a hardware exception raised?
Okay, let's do this directly in GCC inline assembly and see what happens:
int16_t a = -32768;
int16_t b = -1;
__asm__
(
"xorw %%dx, %%dx;" // Clear the DX register (upper-bits of dividend)
"movw %1, %%ax;" // Load lower bits of dividend into AX
"movw %2, %%bx;" // Load the divisor into BX
"idivw %%bx;" // Divide a / b (quotient is stored in AX)
"movw %%ax, %0;" // Copy the quotient into 'b'
: "=rm"(b) // Output list
:"ir"(a), "rm"(b) // Input list
:"%ax", "%dx", "%bx" // Clobbered registers
);
printf("%d\n", b);
This simply outputs an erroneous value: -32768. Still no hardware exception, even though the register storing the quotient (AX) is too small to fit the quotient. So I don't understand why no hardware fault is raised here.
In C language arithmetic operations are never performed within the types smaller than int. Any time you attempt arithmetic on smaller operands, they are first subjected to integral promotions which convert them to int. If on your platform int is, say, 32-bit wide, then there's no way to force a C program to perform 16-bit division. The compiler will generate 32-bit division instead. This is probably why your C experiment does not produce the expected overflow on division. If your platform does indeed have 32-bit int, then your best bet would be to try the same thing with 32-bit operands (i.e. divide INT_MIN by -1). I'm pretty sure that way you'll be able to eventually reproduce the overflow exception even in C code.
In your assembly code you are using 16-bit division, since you specified BX as the operand for idiv. 16-bit division on x86 divides the 32-bit dividend stored in DX:AX pair by the idiv operand. This is what you are doing in your code. The DX:AX pair is interpreted as one composite 32-bit register, meaning that the sign bit in this pair is now actually the highest-order bit of DX. The highest-order bit of AX is not a sign bit anymore.
And what you did you do with DX? You simply cleared it. You set it to 0. But with DX set to 0, your dividend is interpreted as positive! From the machine point of view, such a DX:AX pair actually represents a positive value +32768. I.e. in your assembly-language experiment you are dividing +32768 by -1. And the result is -32768, as it should be. Nothing unusual here.
If you want to represent -32768 in the DX:AX pair, you have to sign-extend it, i.e. you have to fill DX with all-one bit pattern, instead of zeros. Instead of doing xor DX, DX you should have initialized AX with your -32768 and then done cwd. That would have sign-extended AX into DX.
For example, in my experiment (not GCC) this code
__asm {
mov AX, -32768
cwd
mov BX, -1
idiv BX
}
causes the expected exception, because it does indeed attempt to divide -32768 by -1.
When you get an integer overflow with integer 2's complement add/subtract/multiply you still have a valid result - it's just missing some high order bits. This behaviour is often useful, so it would not be appropriate to generate an exception for this.
With integer division however the result of a divide by zero is useless (since, unlike floating point, 2's complement integers have no INF representation).
Contrary to what this article says, the above did NOT cause a hardware exception
The article did not say that. Is says
... they generate a division error if the source operand (divisor) is zero or if the quotient is too large for the designated register
Register size is definitely greater than 16 bits (32 || 64)
From the relevant section on integer overflow:
Unlike the add, mul, and imul
instructions, the Intel division
instructions div and idiv do not set
the overflow flag; they generate a
division error if the source operand
(divisor) is zero or if the quotient
is too large for the designated
register.
The size of a register is on a modern platform either 32 or 64 bits; 32768 will fit into one of those registers. However, the following code will very likely throw an integer overflow execption (it does on my core Duo laptop on VC8):
int x= INT_MIN;
int y= -1;
int z= x/y;
The reason your example did not generate a hardware exception is due to C's integer promotion rules. Operands smaller than int get automatically promoted to ints before the operation is performed.
As to why different kinds of overflows are handled differently, consider that at the x86 machine level, there's really no such thing a multiplication overflow. When you multiply AX by some other register, the result goes in the DX:AX pair, so there is always room for the result, and thus no occasion to signal an overflow exception. However, in C and other languages, the product of two ints is supposed to fit in an int, so there is such a thing as overflow at the C level. The x86 does sometimes set OF (overflow flag) on MULs, but it just means that the high part of the result is non-zero.
On an implementation with 32-bit int, your example does not result in a divide overflow. It results in a perfectly representable int, 32768, which then gets converted to int16_t in an implementation-defined manner when you make the assignment. This is due to the default promotions specified by the C language, and as a result, an implementation which raised an exception here would be non-conformant.
If you want to try to cause an exception (which still may or may not actually happen, it's up to the implementation), try:
int a = INT_MIN, b = -1, c = a/b;
You might have to do some tricks to prevent the compiler from optimizing it out at compile-time.
I would conjecture that on some old computers, attempting to divide by zero would cause some severe problems (e.g. put the hardware into an endless cycle of trying to subtract enough so the remainder would be less than the dividend until an operator came along to fix things), and this started a tradition of divide overflows being regarded as more severe faults than integer overflows.
From a programming standpoint, there's no reason that an unexpected divide overflow should be any more or less serious than an unexpected integer overflow (signed or unsigned). Given the cost of division, the marginal cost of checking an overflow flag afterward would be pretty slight. Tradition is the only reason I can see for having a hardware trap.