主要出口后的分段故障

时间:2016-10-05 18:39:02

标签: c++ segmentation-fault segment-tree

我已尝试在gdb中执行以下代码,但是使用gdb我没有看到任何分段错误但没有gdb如果我在独立模式下运行以下代码,则会发生分段错误。该代码与使用分段树实现的范围和查询相关。

#include <iostream>
#include <vector>
using namespace std;

class segmentTree
{
    private:
        vector<int> a;
        void constructUtil(vector<int>& , int , int , int );
        int queryUtil(int , int , int , int , int );
        void updateUtil(int , int , int , int , int );
    public:
        segmentTree(vector<int> );
        int query(int , int );
        void update(int , int );
        ~segmentTree();
};

segmentTree::segmentTree(vector<int> v)
{
    int n = v.size();
    a.resize((2*n) - 1);
    constructUtil(v, 0 , n - 1, 0);
}

segmentTree::~segmentTree()
{
    a.clear();
}

void segmentTree::constructUtil(vector<int>& v, int start, int end, int i)
{
    if(start == end)
    {
        a[i] = v[start];
    }
    else
    {
        int mid = start + ((end - start) >> 1);
        constructUtil(v, start, mid, ((2*i) + 1));
        constructUtil(v, mid + 1, end, ((2*i) + 2));
        a[i] = a[(2*i) + 1] + a[(2*i) + 2];
    }
}

int segmentTree::queryUtil(int ss, int se, int rs, int re, int i)
{
    if(se < rs || re < ss)
    {
        return 0;
    }
    else if(rs <= ss && se <= re)
    {
        return  a[i];
    }
    else
    {
        int sm = ss + ((se - ss) >> 1);
        return queryUtil(ss, sm, rs, re, 2*i + 1) + queryUtil(sm + 1, se, rs, re, 2*i + 2);
    }
}

int segmentTree::query(int l, int r)
{
    int n = ((a.size() + 1) >> 1);
    if(l < 0 || r > n-1)
    {
        return 0;
    }
    return queryUtil(0, n-1, l , r, 0);
}

void segmentTree::updateUtil(int ss, int se, int i, int si, int x)
{
    if(ss > i || se < i)
    {
        return ;
    }
    else if(ss == se)
    {
        a[si] = x;
    }
    else
    {
        int sm = ss + ((se - ss) >> 1);
        updateUtil(ss, sm, i, (2*si) + 1, x);
        updateUtil(sm + 1, se, i, (2*si) + 2, x);
        a[si] = a[(2*si) + 1] + a[(2*si) + 2];
    }
}

void segmentTree::update(int i, int x)
{
    int n = ((a.size() + 1) >> 1);
    if(i < 0 || i > n-1)
    {
        return ;
    }
    else
    {
        updateUtil(0, n-1, i, 0, x);
    }
}

int main()
{
    int arr[] = {1, 3, 5, 7, 9, 11};
    int n = sizeof(arr)/sizeof(arr[0]);
    vector<int> v(arr, arr + n);

    segmentTree st(v);

    // Print sum of values in array from index 1 to 3
    cout << "Sum of values in given range = " << st.query(1, 3) << endl;

    // Update: set arr[1] = 10 and update corresponding 
    // segment tree nodes
    st.update(1, 10);

    // Find sum after the value is updated
    cout << "Updated sum of values in given range = " << st.query(1, 3) << endl;
    return 0;
}

1 个答案:

答案 0 :(得分:1)

使用segmentTree::constructUtil考虑v.size() == 3。然后在constructUtil的初始通话中,您有start == 0end == 2

因此我们得到mid = 1

在第二次递归调用中,我们传递start = 1end = 2i = 2start != end因此else已执行。

然而,在elsea[(2*i)+2]被访问(顺便说一下,那里不需要parantheses)。该索引为6

但是,如果你查看a的大小,则会将其显示为2*n-12*3-1 = 5,所以6明显超出范围。

我不知道您对代码的意图是什么,但是存在未定义的行为。您可以通过使用valgrind之类的东西轻松捕获它,将a[...]替换为a.at(...)以进行调试,通过使用gdb逐步执行代码并实际跟踪所有变量(不需要是您的程序具有未定义行为的分段错误)或通过输入调试std::cout语句,其中包含可能导致问题的可变内容。