-1

The program uses Segment Trees to find the sum of given range query. It gives the correct answers to the input enterred. However, at the end of the program after executing all lines from the main function, it displays a segmentation fault. Link to image of the output screen.

The error message on executing run in GDB is:

Program received signal SIGSEGV, Segmentation fault. 0x00007ffff71f0532 in __GI___libc_free (mem=0x617c60) at malloc.c:2967 2967 malloc.c: No such file or directory.

On backtracing with GDB, the problem seems to originate at the line at the beginning of main function declaring vector nums. But I can't see what's wrong with my code. The code involving segment trees seems to be fine. I tried using Valgrind too, but couldn't understand anything.

The code (in C++) is:

#include <bits/stdc++.h>
using namespace std;

class NumArray
{
    public:
    int* st;
    vector<int> nums;
    NumArray(vector<int> num)
    {
        st = new int[num.size()];
        if(num.size() != 0)
        {
            st = constructST(num);
        }
        nums = num;
    }

    int* constructST(vector<int> nums)
    {
        int height = ceil(log(nums.size())/log(2));
        int stSize = 2*(int)pow(2,height)-1;
        constructSTUtil(nums,0,nums.size()-1,st,0);
        return st;
    }

    int constructSTUtil(vector<int> nums,int ss, int se, int* st,int si)
    {
        if(ss == se)
        {
            st[si] = nums[ss];
            return st[si];
        }
        int mid = ss + (se-ss)/2;
        st[si] = constructSTUtil(nums,ss,mid,st,2*si+1) + constructSTUtil(nums,mid+1,se,st,2*si+2);
        return st[si];
    }

    void update(int i, int val)
    {
        int diff = val - nums[i];
        nums[i] = val;
        int n = nums.size();
        updateUtil(st,0,n-1,i,diff,0);
    }

    void updateUtil(int* st,int ss,int se,int i,int diff,int si)
    {
        if(i < ss || i > se)
        {
            return;
        }
        st[si] = st[si] + diff;
        if(se != ss)
        {
            int mid = ss + (se-ss)/2;
            updateUtil(st,ss,mid,i,diff,2*si+1);
            updateUtil(st,mid+1,se,i,diff,2*si+2);
        }
    }

    int sumRange(int i, int j)
    {
        int n = nums.size();
        if(i < 0 || i > j || j > n)
        {
            cout << "Invalid input";
            return -32768;
        }
        return sumRangeUtil(st,0,n-1,i,j,0);
    }

    int sumRangeUtil(int* st,int ss, int se, int qs, int qe, int si)
    {
        if(qs <= ss && qe >= se)
        {
            return st[si];
        }
        if(qs > se || qe < ss)
        {
            return 0;
        }
        int mid = ss + (se-ss)/2;
        return sumRangeUtil(st,ss,mid,qs,qe,2*si+1) + sumRangeUtil(st,mid+1,se,qs,qe,2*si+2);
    }
};

int main()
{
    vector<int> nums;
    nums.push_back(0);
    nums.push_back(9);
    nums.push_back(5);
    nums.push_back(7);
    nums.push_back(3);
    NumArray obj(nums);
    cout << obj.sumRange(4,4) << "\n";
    cout << obj.sumRange(2,4) << "\n";
    cout << obj.sumRange(3,3) << "\n";
    obj.update(4,5);
    obj.update(1,7);
    obj.update(0,8);
    cout << obj.sumRange(1,2) << "\n";
    obj.update(1,9);
    cout << obj.sumRange(4,4) << "\n";
    cout << obj.sumRange(3,4) << "\n";
    return 0;
}
  • Not the immediate problem, but you seem to be leaking memory. You dont have a destructor to clean up `st`. Also may I suggest replacing it with a `std::vector`? – Borgleader Jun 03 '18 at 07:33
  • Your code suffers from multiple collisions of name of function parameters and class fields. You never check that index at which you access `st` is valid so I guess there could be a buffer overrun. Valgrind output would be helpful/ – user7860670 Jun 03 '18 at 07:50

1 Answers1

3

Look at this function

int constructSTUtil(vector<int> nums,int ss, int se, int* st,int si)
{
    if(ss == se)
    {
        st[si] = nums[ss];
        return st[si];
    }
    int mid = ss + (se-ss)/2;
    st[si] = constructSTUtil(nums,ss,mid,st,2*si+1) + constructSTUtil(nums,mid+1,se,st,2*si+2);
    return st[si];
}

that calls it self recursively.

Now add this coutat the start of the function, like:

int constructSTUtil(vector<int> nums,int ss, int se, int* st,int si)
{
    cout << "ss = " << ss << " se = " << se << " si = " << si << endl;

When nums have 5 elements this will give you:

ss = 0 se = 4 si = 0
ss = 0 se = 2 si = 1
ss = 0 se = 1 si = 3
ss = 0 se = 0 si = 7
              ^^^^^^
              ups... out of range for `st`

So when you do:

st[si] = nums[ss];

You are writing out of bounds. In other words, there is something wrong with your algorithm.

BTW:

int stSize = 2*(int)pow(2,height)-1;
     ^^^^^
     Never used in the code

Also it seems rather confusing that you have a member st and also function argument st. And it's also confusing that you assign to st using the return value from constructsST (which is st).

Support Ukraine
  • 42,271
  • 4
  • 38
  • 63