0

for the question https://www.codechef.com/LRNDSA01/problems/MULTHREE

I am getting Runtime Error(SIGSEGV). I wrote the following program but on codechef . I want to know specifically which instruction is creating this error in my program so that i try and remove that. here is the code:

#include <iostream>
using namespace std;

int main() 
{
int t;
cin>>t;
while(t--!=0)
{
    int i,d0,d1,sum;
    long long int K,digit=0;
        
    cin>>K;
    cin>>d0>>d1;

    int arr[K];
    arr[0]=d0;
    arr[1]=d1;
    sum=d0+d1;
    

     for(i=2;i<=K-1;i++)
        {
          arr[i]=sum%10;
         sum=sum+arr[i];
        }


    for(i=0;i<=K-1;i++)
    digit=arr[i]+(digit*10);
    //cout<<digit;

    if(digit/3==0)
    cout<<"YES";
    else
    cout<<"NO";
}

return 0;

}

Nicol Bolas
  • 449,505
  • 63
  • 781
  • 982
Yash Kumar
  • 31
  • 8
  • 2
    Here's some good reading if you'd like to make portable programs: [Why aren't variable-length arrays part of the C++ standard?](https://stackoverflow.com/questions/1887097/why-arent-variable-length-arrays-part-of-the-c-standard) TL;DR: `int arr[K];` would, using standard C++, be `std::vector arr(K);` – Ted Lyngmo Jan 27 '21 at 19:10
  • 1
    _I want to know specifically which instruction is creating this error in my program so that i try and remove that._ - that is what debuggers are for. – Maxim Egorushkin Jan 27 '21 at 19:18
  • 1
    I think you might want to choose a different method to solve your puzzle – Michael Chen Jan 27 '21 at 19:42
  • I ran it in a debugger with the example input on that site. The line that made it crash was `int arr[K];` when `K` was `760399384224` ... that _could_ be a problem :-) – Ted Lyngmo Jan 27 '21 at 19:45

2 Answers2

1

EDIT: Actual possible solution at the end.

First of all as Ted Lyngmo already said: Your array initialization is not C++ standard compliant (i think some compilers support it, but i have never used it). You could either use C++ STL vectors or pointers.

Using pointers your code could look like this (note that you have to delete every memory that you initialize):

int * arr = new int[K];
// Do your test case and before (!) the end of
// the while loop free the memory
delete[] arr;

Using vectors your code could look like this (std::vector takes care of all memory management for you):

#include <vector>
std::vector<int> arr(K);

One thing that could cause a SIGSEGV is an invalid write to an address. If for example K is less than 2 you are writing to memory locations that you don't safely own and the OS could kill your process. Your algorithm either doesn't work for K < 2 or it is missing an edge case.

// Make sure that K >= 2
// If K < 2 the following lines could cause SIGSEGV
arr[0] = d0;
arr[1] = d1;

Also you might want to check how much memory you are actually allocating with your vector.

The task on CodeChef specifies: 2 ≤ K ≤ 10^12

You are trying to allocate every digit for your number as an integer. An integer usually takes about 4 bytes so on difficult cases your program attempts to allocate 4B * K = 3.64 TiB of memory. That might be the problem as i don't think you have multiple terabytes of RAM at hand. You might want to try a different attempt at solving the puzzle that doesn't allocate as much memory.

Note: a single decimal digit takes a bit less than 4 bit (half a byte) to store. which is still more than you can allocate. So you might want to think about a solution where you dont have to calculate in beforehand every single digit, but iterate through the digits of your unknown number.

Michael Chen
  • 574
  • 3
  • 11
0

Its a compiler error, it needs to know the precise size of an array you provided a variable that is undefined at compile time, to make it dynamic you need a pointer array that is evaluated and created at runtime and declaring variables inside a loop is no good, declare then at the start an use them.

#include <iostream>
#include <string>

int main() {
    uint32_t * arr, K;
      
    std::string in;

    std::cout << "Array size -> ";
    std::cin  >> in;

    K = std::stoi(in);
    arr = new uint32_t[K];

    std::cout << "arr[0] -> ";
    std::cin  >> in;
    arr[0] = std::stoi(in);

    std::cout << "arr[0] * 2 -> " << arr[0] * 2;

    delete [] arr;

    return 0;
}
SrPanda
  • 854
  • 1
  • 5
  • 9
  • That doesn't seem to be the problem of focus here. See the comments on OPs questions. Many compilers can handle initializations like that. I'm using `g++ (MinGW.org GCC Build-2) 9.2.0` for example (quite common) and it compiles and runs the program just fine. – Michael Chen Jan 27 '21 at 19:45
  • No, this is not the problem. – Ted Lyngmo Jan 27 '21 at 19:47
  • Another side note to your implementation: `std::stoi` returns a signed integer. You should probably be using `std::stoul` to return an uint32_t. Or you could just pipe the istream directly into the variable like this: `std::cin >> K`. – Michael Chen Jan 27 '21 at 19:48
  • It might be multiple problems, the example is more to give an idea with how to create a dynamic array safely – SrPanda Jan 27 '21 at 19:52
  • Using an `uint32_t` is intentional, there is no negative length array – SrPanda Jan 27 '21 at 19:54
  • Using a `vector` would also use dynamic allocation but unless OP has a _huge_ amount of memory, it'll still fail. When K=760399384224, the allocation would require ~3 TB and Kmax would require 4 TB exactly. – Ted Lyngmo Jan 27 '21 at 19:58
  • `K` is set by a `cin`, i cant believe that he is adding that number and not realizing – SrPanda Jan 27 '21 at 20:09