How can I avoid this integer overflow? - c++

I was solving the famous leetcode question 4sum and I came up with an optimal solution but I am facing an integer overflow even though I have used long long int datatype.
class Solution {
public:
vector<vector<int>> fourSum(vector<int>& nums, int target) {
vector<vector<int>> res;
if(nums.empty()){
return res;
}
int n = nums.size();
sort(nums.begin(), nums.end());
for(int i=0; i<n; i++){
for(int j=i+1; j<n; j++){
long long int temp = target - (nums[j] + nums[i]);
int front = j+1;
int back = n-1;
while(front < back){
long long int twosum = nums[front] + nums[back];
if(twosum < temp){
front++;
}
else if(twosum > temp){
back--;
}
else{
vector<int> ans(4,0);
ans[0] = (nums[i]);
ans[1] = (nums[j]);
ans[2] = (nums[front]);
ans[3] = (nums[back]);
res.push_back(ans);
while(front < back && nums[front] == ans[2]) ++front;
while(front < back && nums[back] == ans[3]) --back;
}
}
while(j+1 < n && nums[j+1] == nums[j]) ++j;
}
while(i+1 < n && nums[i+1] == nums[i]) ++i;
}
return res;
}
};
Here is the error message:
Line 12: Char 41: runtime error: signed integer overflow: -294967296 - 2000000000 cannot be represented in type 'int' (solution.cpp)
SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior prog_joined.cpp:21:41

Although in this compound statement
long long int temp = target - (nums[j] + nums[i]);
the destination variable temp is of sufficient size, the actual arithmetic happens on the types determined from integer promotion rules, applied to target and nums, both of which are of just int.
You'll have to upcast them to a sufficiently large type before the arithmetic operator takes effect. Like this
long long int temp = (long long int)target - ((long long int)nums[j] + (long long int)nums[i]);

Related

runtime error: addition of unsigned offset/UndefinedBehaviorSanitizer: undefined-behavior

I am not able to find where is my vector going out of bound. This is solution of leetcode question 695.
Error:
Line 1034: Char 34: runtime error: addition of unsigned offset to 0x610000000040 overflowed to 0x610000000028 (stl_vector.h)
SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior /usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../../include/c++/9/bits/stl_vector.h:1043:34
Code:
int maxAreaOfIsland(vector<vector<int>>& grid) {
int n = grid.size();
int m = grid[0].size();
vector<vector<int>> vis(n,vector<int>(m,0));
int ans =0 ;
for(int i=0;i<n;i++) {
for(int j=0;j<m;j++) {
int count = 0;
if(grid[i][j]==1 && !vis[i][j]) {
vis[i][j]=1;
queue<pair<int,int>> q;
q.push({i,j});
count++;
while(!q.empty()) {
int a = q.front().first;
int b = q.front().second;
q.pop();
int r[] = {-1, 1, 0, 0};
int c[] = {0, 0, 1, -1};
for(int z=0; z<4; z++) {
int x = a + r[z];
int y = b + c[z];
if(x<n && y<m && grid[x][y]==1 && !vis[x][y]) {
vis[x][y]=1;
q.push({x,y});
count++;
}
}
}
ans = max(ans,count);
}
}
}
return ans;
}
I expect
if(x<n && y<m && grid[x][y]==1 && !vis[x][y]) {
should be
if (x>=0 && y>=0 && x<n && y<m && grid[x][y]==1 && !vis[x][y]) {
Notice in the error addition of unsigned offset to 0x610000000040 overflowed to 0x610000000028. In other words the unsigned offset is negative (when regarded as a signed quantity).
Always be careful mixing signed and unsigned arithmetic.
I am not able to find where is my vector going out of bound
The simplest way(IMO) to find out where you're going out of bounds in the vector is to use std::vector::at instead of std::vector::operator[].
When using at you'll get an out_of_range exception if the index is greater or equal to the size of the vector. For example, use grid.at(i).at(j) instead of grid[i][j] and so on for other as well.

Heap corruption on dynamic programming problem

I'm getting an heap corruption error and I can't figure out where it is.
The problem is a coin change problem using dynamic programming. C is the array with the coin values, n is the size of the array, T is the target change, usedCoins is an array where the number of used coins should be mapped (i.e if C[1] = 2 and 3 2-coins are used, usedCoins[2] = 2 with all other indexes to 0.
Here's the code:
bool changeMakingUnlimitedDP(unsigned int C[], unsigned int n, unsigned int T, unsigned int usedCoins[]) {
static auto minCoins = new unsigned int[T+1]{UINT_MAX};
minCoins[0] = 0;
static auto lastCoin = new unsigned int[T+1]{0};
for(int i = 0; i < n; i++)
usedCoins[i] = 0;
for(int i = 0; i < n; i++){
for(int j = 1; j <= T; j++){
if(j >= C[i]){
minCoins[j-C[i]] == 0? minCoins[j] = 1 : minCoins[j] = std::min(1 + minCoins[j - C[i]], minCoins[j-C[i]]);
lastCoin[j] = i;
}
}
}
while(T > 0){
unsigned int last = lastCoin[T];
if(last == UINT_MAX || last < 0) return false;
usedCoins[last]++;
T -= C[last];
}
free(minCoins);
free(lastCoin);
return true;
}
When running on debug mode it goes through.

std::bad_array_new_length for large numbers

I try to run following code:
#include <stdio.h>
#include <stdlib.h>
int find_next(int act, unsigned long long survivors[], int n)
{
int i = act;
while (survivors[i] == 0)
{
i++;
i = i % n;
}
i = (i + 1) % n; // found first one, but need to skip
while (survivors[i] == 0)
{
i++;
i = i % n;
}// thats the guy
return i;
}
int main()
{
long long int lines;
long long int* results;
scanf_s("%llu", &lines);
results = new long long int[lines];
for (long long int i = 0; i < lines; i++) {
unsigned long long n, k;
scanf_s("%llu", &n);
scanf_s("%llu", &k);
unsigned long long* survivors;
survivors = new unsigned long long[n];
for (int m = 0; m < n; m++) {
survivors[m] = 1;
}
int* order;
order = new int[n];
int p = 0;
int act = 0;
while (p < n - 1)
{
act = find_next(act, survivors, n);
order[p] = act;
survivors[act] = 0; // dies;
p++;
}
order[p] = find_next(act, survivors, n);
if (k > 0)
{
results[i] = order[k - 1] + 1;
}
else
{
results[i] = order[n + k] + 1;
}
delete[] survivors;
delete[] order;
}
for (long long int i = 0; i < lines; i++) {
printf("%llu\n", results[i]);
}
delete[] results;
return 0;
}
My inputs are:
1
1111111111
-1
I am getting an exeption:
std::bad_array_new_length for large numbers
At line:
survivors = new unsigned long long[n];
How should I fix it that it wont show for such large numbers?
So far I tried all numeric types of n -> long long int, unsigned long and so on but everytime I was failing. Or maybe there is no way around that?
How should I fix it that it wont show for such large numbers?
Run the program on a 64 bit CPU.
Use a 64 bit operating system.
Compile the program in 64 bit mode.
Install sufficient amount of memory. That array alone uses over 8 gigabytes.
Configure operating system to allow that much memory be allocated for the process.
P.S. Avoid owning bare pointers. In this case, I recommend using a RAII container such as std::vector.

invalid type argument of unary '*' (have 'int') lowest element in array

I want to find the lowest element in the array using a function lowest(). But this program does not work. It shows the error
invalid type argument of unary '*' (have 'int')
Here is the code:
#include <stdio.h>
int lowest(int *j, int n) { //For finding the lowest element
int i, temp, tempAdd;
for (i = 0; i < n; i++) {
if (temp > *(j + i))
temp = *(j + i);
tempAdd = j + i;
}
return tempAdd; //Sends the address of the lowest element
}
int main() {
int n;
printf("Enter the number of inputs: ");
scanf("%d", &n);
int arr[n], i;
for (i = 0; i < n; i++) {
printf("\nEnter element no. %d: ", i + 1);
scanf("%d", &arr[i]);
}
for (i = 0; i < n; i++) {
printf("Element no. %d is %d with the address %d.\n", i + 1, *(arr + i), arr + i);
}
int low = lowest(arr, n); //Saves the address of the lowest element.
printf("\nThe Lowest element in the list is %d with address %d.", *low, low); //Error occurs
return 0;
}
Your function lowest has problems:
int lowest(int *j, int n) { //For finding the lowest element
int i, temp, tempAdd;
for(i = 0; i < n; i++) {
if(temp > *(j + i))
temp = *(j + i);
tempAdd = j + i;
}
return tempAdd; //Sends the address of the lowest element
}
you forgot the braces around the if block. Indentation does not determine block structure in C.
the semantics are inconsistent: you return the index to the lowest element but you set tempAdd to j + i which is a pointer to the lowest element.
you do not initialize temp, nor tempAdd. The behavior is undefined.
it is confusing to name a pointer j, j is usually designates an integer index. Use p.
Here is a simpler version:
int lowest(int *p, int n) { //For finding the lowest element
int i, tempAdd = 0;
for (i = 1; i < n; i++) {
if (p[i] < p[tempAdd]) {
tempAdd = i;
}
}
//Return the index of the lowest element
return tempAdd;
}
In main, you should modify the code because low is not a pointer:
printf("\nThe Lowest element in the list is %d with address %d.",
arr[low], &arr[low]);
For printing address you can use %p as below.
printf("\nThe Lowest element in the list is %d with address %p.", low, low);
#include<stdio.h>
int *lowest(int *j, int n) { //For finding the lowest element
int i, temp;
int *tempAdd;
temp=*j;
tempAdd=j;
for(i = 0; i < n; i++) {
if(temp > *(j + i)){
temp = *(j + i);
tempAdd = j + i;
}
}
return tempAdd; //Sends the address of the lowest element
}
Along with this correct the following line
int low = lowest(arr, n); to int *low = lowest(arr, n);
the lowest function should be:
int *lowest(int *j, int n) { //For finding the lowest element
int i, temp = *j;
int *tempAdd = NULL;
for(i = 0; i < n; i++) {
if(temp > *(j + i))
temp = *(j + i);
tempAdd = j + i;
}
return tempAdd; //Sends the address of the lowest element
}
and in your main function: use int *low instead of int low and use %p to display the variable address.
Here the first iteration of a fixed function. It still is not 100% as I would write it but restricts itself to address the problem of the question.
As you want to return the address, I adjusted the return type as well as the type of variable tempAdd
int* lowest(int *j, int n) { //For finding the lowest element
int i, temp;
int *tempAdd;
for(i = 0; i < n; i++) {
if(temp > *(j + i)) {
temp = *(j + i);
tempAdd = j + i;
}
}
return tempAdd; //Sends the address of the lowest element
}
E.g., for parameter n = 0 the return value of your function would be undefined if no further changes to the function are made.
As variable temp is also not initially initialized, it is also possible that the address returned is undefined in case, that no member of the array is smaller than the (random) value of variable temp.
Here, a slightly more robust version:
int* lowest(int *j, int n) { //For finding the lowest element
if( 0 == n ) return NULL; // empty arrays have no smallest element!
int i;
int temp = j[0]; // instead of using pointer arithmetic you can also use this syntax.
int *tempAdd = j; // initially the first element is allegedly the smallest...
for(i = 1; i < n; i++) // loop starts at index 1 now!
{
if(temp > *(j + i)) {
temp = *(j + i);
tempAdd = j + i;
}
}
return tempAdd; //Sends the address of the lowest element
}
Your function main() also has its issues. You cannot create an automatic (stack-located) array of dynamic size, which is what you try. Instead, if you want to query the user for the size of the array, you would have to resort to a heap-based array, instead. Or you would query for a size, which is smaller or equal an arbitrary chosen fixed size of your stack based array.
int main() {
int n = 0;
printf("Enter the number of inputs (1..500): ");
scanf("%d", &n);
if( n < 1 || n > 500 ) {
puts("Invalid input.");
return -1;
}
int arr[500]; // 500 was chosen because most likely no one is crazy enough to manually type in more values by hand ;)
int i;
for(i = 0; i < n; i++) {
printf("\nEnter element no. %d: ", i + 1);
scanf("%d", &arr[i]);
}
for(i = 0; i < n; i++) {
printf("Element no. %d is %d with the address %d.\n", i + 1, *(arr + i), arr + i);
}
int * low = lowest(arr, n); //Saves the address of the lowest element.
printf("\nThe Lowest element in the list is %d with address %p.", *low, low); //Error occurs
return 0;
}
Also changed the formatting to "%p" for pointer.
Also changed type of low from int to int *.
Last not least you would have to change main() further, if you were to allow 0 array size. Why? Because in your printf you write ...,*low,.... As lowest() would return NULL in the case of n = 0, you would dereference a NULL pointer, which leads to a nasty run time error.
From a design perspective, eventually, returning the address in lowest() appears to break the level of abstraction, related to the fact that you pass in the length of the array. You mix two styles, basically.
STL- style would be: int * lowest( int *begin, int * end )
Vintage- style would be: int lowestIndex( int *arr, int n)
The second version, though would have the problem that you cannot express a "no result" outcome. E.g if Array size is 0 or other invalid arguments are being passed to the function. Thus, often people would do it this way instead:
bool lowestIndex( int * arr, int n, int *result )
... where the return value indicates success and the result content is only valid if the return value was true.

arithmetic overflow in codility test

I did the codility demo test "NumberOfDiscIntersections":
https://codility.com/programmers/lessons/4
I've got: perf = 100% and correctness 87%
All tests but one went fine:
overflow
arithmetic overflow tests
Why was my long long, not enough ? I can't figure what went wrong!
#include <algorithm>
int solution(const vector<int> &A)
{
// write your code in C++11
vector<long long > vec_max;
for(int i = 0; i < A.size(); ++i)
{
vec_max.push_back( A[i] + i );
}
std::sort(vec_max.begin(),vec_max.end()); // sort by max
int step = 1;
int counter = 0;
for(int i = A.size() - 1; i > -1; --i)
{
std::vector<long long>::iterator low;
int nb_upper = A.size() - ( lower_bound( vec_max.begin(),vec_max.end(), (long long) (i - A[i]) ) - vec_max.begin() );
counter += nb_upper - step;
++step;
}
if (counter > 10000000)
{
return -1;
}
else
{
return counter;
}
}
If the A array is very large, you might end up adding large indices to the counter int variable. The step variable is quite small compared to it
counter += nb_upper - step;
and this is likely where you're overflowing a variable.