Segmentation fault in C++ using vectors

元气小坏坏 提交于 2020-01-04 05:19:11

问题


I'm having trouble with a segmentation fault caused by the following line:

heapVec[currentsize] = *(new Node(d));

What am I doing wrong here?

#include <vector>
using namespace std;

class Node {
private:
    int data;
public:
    Node(int);
    // ~Node();
};

class Heap {
private:
    vector<Node> heapVec;
    int currentsize;
public:
    Heap();
    // ~Heap();
    void insert(int);
    void extractMin();
    void reduceKey();
};

Node::Node(int d) {
    data = d;
}

void Heap::insert(int d) {
    heapVec[currentsize] = *(new Node(d));
    currentsize++;
}

Heap::Heap() {
    // this is the default constructor
    currentsize = 0;
}

int main() {
    Heap *h = new Heap;
    h->insert(10);
}

回答1:


A vector doesn't grow automatically when you write out of its bounds using subscript operator. To insert to the end of the vector (increasing its size) use this:

heapVec.push_back(Node(d));

Also don't use *(new Node(d)), it won't segfault, but its a memory leak.




回答2:


Before you access a vector by index you need to allocate space for it

 heapVec[currentsize] = *(new Node(d));

heapVec.resize(currentsize + 1) should do it. It will ensure that heapVec has at least currentsize + 1 elements and you can access currentsize.

One way to avoid this is by modifying your function. As you only are adding to the end of the vector.

void Heap::insert(int d) {
    heapVec.push_back( Node(d) );
    currentsize++;
}

Please note that you have vector<Node> and not vector<Node*> so you don't need the new call.

Also vector has a size() method so you don't need to duplicate it by having your own currentSize




回答3:


First, you're writing outside the range of the vector, which is causing the segmentation fault. You need to either resize the vector to be large enough to contain it, or use push_back() to resize it for you.

Second, you have a memory leak - you're creating a Node with new for no good reason, then copying it into the vector, then losing the pointer and so never deleting the first object.

What you want is

heapVec.push_back(Node(d));

or in C++11

heapVec.emplace_back(d);

I would also get rid of your redundant currentsize variable and use heapVec.size() instead. Also, don't use new to create the local heap in main(); in general don't use new unless you really have to, and when you do, always use smart pointers or very carefully written code to make sure the object is deleted.




回答4:


I am pretty sure that you got this error because you tried to write out of vector's boundaries. Don't use array syntax (although you're allowed) for operations on vector: in Heap::insert() use heapVec.push_back().

Another thing is that you should not bother using Node type if it contains only int member. Why not just having vector<int>?

You can simplify your class further. When you already have std::vector, your currentsize member is redundant (unnecessary) as vector::size() will tell you the current size of it.




回答5:


What am I doing wrong here?

A few different things, including the bug that results in your crash. See my comments below.

#include <vector>

// Never, ever, say "using namespace std;" even if (especially if) your textbook says to.
// using namespace std;
using std::vector;

class Node {
private:
    int data;
public:
    // Prefer to define small functions in-class so that they are automatically inline
    // Prefer initialization list to assignment. This is mostly style in your case, but
    // does matter in more complex cases.
    Node(int d) : data(d) {}
    // ~Node();
};

class Heap {
private:
    vector<Node> heapVec;
    // int currentsize;  "currentsize" is redundant, and thus error-prone.
    // heapVec always knows what size it is, so just ask it whenever you need to know.
public:
    // In this trivial example, with currentsize gone, you don't need any constructor.
    // Heap();
    // ~Heap();
    void insert(int);
    void extractMin();
    void reduceKey();
};

void Heap::insert(int d) {
    // This is your crash bug -- std::vector::operator[] doesn't automatically extend
    // the size of the vector (unlike, say, std::map::operator[], which does).
    // Also, your use of "new" here is unconventional, and buggy. You have a memory leak.
    // It is possible to write perfectly useful C++ programs while never invoking "new"
    // directly.
    // heapVec[currentsize] = *(new Node(d));
    // currentsize++;

    // Instead, use std::vector::push_back() or std::vector::insert(), *and* don't call
    // new.
    heapVec.push_back(Node(d));
}


int main() {
    // In this example (and, I bet, in your real-world program), you don't need "new"
    Heap h;
    h.insert(10);
}



回答6:


There are two errors you are doing: The first is the problem you have, and it's that you insert into a specific place in heapVec without allocating memory for it. This is solved either by calling heapVec.reserve(...) in the Heap constructor, or by calling heapVec.push_back(Node(d)) in insert.

The other problem is that when inserting nodes into the vector, you allocate new node and get the contents of it, which will make a copy that is stored in the vector. But you don't store the actual allocated pointer, which means you have a memory leak. You should not allocate in this case.



来源:https://stackoverflow.com/questions/8138071/segmentation-fault-in-c-using-vectors

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!