【问题标题】:Attempt to get size of vector causes segfault尝试获取向量的大小会导致段错误
【发布时间】:2014-08-29 04:07:52
【问题描述】:

我一直在尝试实现 Heap 数据类型,但我碰壁了。

由于很多以前的答案都要求提供 moar 代码,所以这里是:

#include <iostream>
#include <vector>
#include <iomanip>

using namespace std;

template <typename T> void display_array(vector<T> arr, bool endline = true)
{
    cout << arr.size() << endl;
    for (int i = 0; i < arr.size() - 1; i++) cout << arr[i] << ", ";
    cout << arr[arr.size() - 1];
    if(endline) cout << endl;
}

template <class T> class Heap
{
    //typedef T Node;
//    setw(...);
//private:

public:
    vector<T>* elems;
    Heap() : elems(nullptr)
    {
        this->elems = new vector<T>;
    }

    Heap(vector<T> e)
    {
        this->elems = new vector<T>(e);
    }

    Heap(vector<T>* e)
    {
        this->elems = e;
    }

    Heap(Heap<T>& h)
    {
        this->elems = new vector<T>(h.elems);
    }

    ~Heap()
    {
        delete elems;
    }

    T elemAt (int index)
    {
        return (*(this->getElems())) [index];
    }

    vector<T>* getElems()
    {
        return this->elems;
    }

    int parent (int index)
    {
        return index / 2;
    }

    long getSize()
    {
        return this->getElems()->size();
    }

    int left (int index)
    {
        return 2 * index;
    }
    T leftElem (int index)
    {
        return this->elems [2 * index];
    }

    int right (int index)
    {
        return 1 + 2 * index;
    }
    T rightElem (int index)
    {
        return this->elems [1 + 2 * index];
    }

    bool withinHeap (int index)
    {
        return index <= (this->getSize());
    }

    void maxHeapify(int index)
    {
        int largest = index;
        int l = left(index);
        int r = right(index);

        if (withinHeap(l) && elemAt(l) > elemAt(index))
        {
            if (withinHeap(r) && elemAt(r) > elemAt(l))
            {
                largest = r;
            }
            largest = l;
        }

        if (largest != index)
        {
            int temp = elemAt(index);
            elemAt(index) = elemAt(largest);
            elemAt(largest) = temp;
            delete temp;
        }
        /* or return withinHeap(l) && elemAt(l) > elemAt(index) ? withinHeap(r) && elemAt(r) > elemAt(l) ? r : l : index; :) */
    }

    void display(int current, int indent)
    {
        if(withinHeap(left(current))) display(left(current), indent + 4);
        if (indent > 0) cout << setw(indent) << " ";
        cout << elemAt(current) << endl;
        if(withinHeap(right(current))) display(right(current), indent + 4);
    }
};

int main()
{
    vector<int> vec {2, 5, 4, 12, 3, 9};
    Heap<int>* h = new Heap<int>(vec);
    display_array(*h->getElems());

    h->display(0, 0);


    return 0;
}

最后一条语句 (h-&gt;display(0,0)) 会导致段错误。我已将其范围缩小到 getSize() 函数。

在 gdb 中,print this.elemsprint *this.elems 没问题(它们返回对象跟踪或它们所称的任何内容),但是当我键入 print *this.elems-&gt;size() gdb 时会回复

Cannot access memory at address 0xbf7fffef

我对 C++ 和 gdb 以及所有东西都很陌生。这里有什么问题?

【问题讨论】:

  • 仅供参考,您的 Heap 课程可以使用 3 行 main() 程序来破解。都是因为缺少用户定义的赋值运算符..
  • 你真的不需要/想要一个指向vector的指针。
  • 问题不在于您的 getSize() 函数,而在于您的算法。我在 getSize() 中放了一条 cout 语句,我的终端被垃圾邮件发送了。我的猜测是,由于递归函数存在缺陷,您会遇到 Stack Overflow。
  • 您的代码看起来更像 Java 和 C# 而不是 C++。你为什么在那里做那个 new Heap ?你不能直接创建对象吗?如果为它分配动态内存,则应在使用后删除 Heap。 C++ 没有垃圾收集器。
  • @SohamChowdhury 您在 main() 函数中有泄漏。我还可以通过将一个Heap 对象简单地分配给另一个对象来创建一个。 Heap h1; Heap h2; h2 = h1; 不仅会泄漏,还会在同一个指针上调用delete 两次,导致未定义的行为,可能会崩溃。鉴于简单的 3 行程序会造成这种破坏,希望它表明这并不像您想象的那么简单或直观。

标签: c++ segmentation-fault


【解决方案1】:

考虑到代码中的所有 C++ 技术(均有效),问题似乎是您的 display 函数导致堆栈溢出。

如果您将调用 left() 替换为 left() 实际执行的操作,您可以清楚地看到它:

void display(int current, int indent)
{
    if (withinHeap(2 * current)) 
        display(2 * current, indent + 4);
    //...
}

如果我们调用display(0, 0);,则该函数将无法返回,因为您在循环中使用相同的参数值调用display

withinHeap 除了检查参数是否在范围内之外什么都不做,并且不会以任何方式更改Heap 对象。由于0 在范围内,对withinHeap 的调用总是返回true。所以从这个函数开始你就遇到麻烦了。

我不会讨论如何解决这个问题,因为这是一个算法问题,而不是 C++ 问题。但是我指出的是您的代码导致错误的位置。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-12-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-07-03
    • 1970-01-01
    相关资源
    最近更新 更多