2011-11-15 29 views
2
我在與造成以下行分段錯誤麻煩

分段故障++使用矢量

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

我在做什麼錯在這裏?

#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); 
} 
+0

代碼'*(new Node(d))'完全錯誤。它分配Node類的對象,並忘記了指針。這是內存泄漏的定義。您必須更改'vector heapVec;'向'vector heapVec;'或使用類似'boost :: ptr_vector heapVec;'的東西。 – Arpegius

+0

請勿使用矢量。您很可能最終會發生內存泄漏,因爲您將不得不手動刪除每個向量成員。 只要做,Dani在下面說,你很好。 – Ben

+0

+1,用於演示您遇到的問題的完整,最簡單的程序。請參閱http://sscce.org爲什麼這是有價值的原因。 –

回答

8

當你寫出來的使用標其邊界的矢量不會自動增長運營商。要插入到向量的末尾(增加其大小)使用此:

heapVec.push_back(Node(d)); 

也不要使用*(new Node(d)),也不會出現段錯誤,但它的內存泄漏。

2

之前通過索引來訪問一個向量,你需要爲它

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

heapVec.resize(currentsize + 1)應該這樣做分配空間。它將確保heapVec至少具有currentize + 1元素,並且您可以訪問currentise

避免這種情況的一種方法是修改您的功能。因爲你只是添加到矢量的末尾。

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

請注意,您必須矢量<節點>,而不是矢量<節點*>,所以你不需要電話。

而且載體具有大小()方法,所以你並不需要通過擁有自己的currentSize複製它

+0

我明白你的意思,但這是給我以下內容: minheap.cpp:33:錯誤:沒有匹配函數調用'節點::節點()' minheap.cpp:28:注意:候選人是: Node :: Node(int) minheap.cpp:8:note:Node :: Node(const Node&) –

+0

你需要一個默認的構造函數來存放你在std :: vector中的任何東西。 –

+0

@ DanielO'Connor:當然,您需要爲Node定義默認構造函數。沒有一個,你不能使用節點的std :: vector。 – Arne

-1

您正在做的錯誤有兩種:第一種是您遇到的問題,它是您插入到heapVec中的特定位置而未爲其分配內存。這可以通過在Heap構造函數中調用heapVec.reserve(...)或通過在insert中調用heapVec.push_back(Node(d))來解決。

另一個問題是,當向節點中插入節點時,會分配新節點並獲取它的內容,這會創建存儲在向量中的副本。但是你不存儲實際分配的指針,這意味着你有內存泄漏。在這種情況下你不應該分配。

+2

'reserve()'沒有幫助,除了用更微妙的未定義行爲來替換分段錯誤 - 訪問超出數組末尾的對象仍然是非法的。你需要在訪問它們之前調整大小()。 –

1

首先,你寫的是向量的範圍之外,這是導致分段錯誤。您需要調整矢量的大小以容納它,或者使用push_back()來爲您調整大小。

其次,你有一個內存泄漏 - 你創建一個Nodenew沒有什麼好的理由,然後將其複製到向量中,然後丟失指針,因此從不刪除第一個對象。

你想要的是

heapVec.push_back(Node(d)); 

或C++ 11

heapVec.emplace_back(d); 

我也想擺脫你的多餘currentsize變量和使用heapVec.size()代替。另外,請勿使用newmain()中創建本地堆;一般情況下不要使用new,除非你真的必須,而且當你這樣做的時候,總是使用智能指針或非常仔細的代碼來確保刪除對象。

0

我很確定你得到這個錯誤,因爲你試圖寫出矢量的邊界。不要使用數組語法(雖然您可以)對矢量進行操作:在Heap::insert()中使用heapVec.push_back()

另一件事是你不應該打擾使用Node類型,如果它只包含int成員。爲什麼不只是有vector<int>

您可以進一步簡化課程。當你已經有std::vector,你的currentsize成員是多餘的(不必要),因爲vector::size()會告訴你它的當前大小。

0

What am I doing wrong here?

一些不同的事情,包括導致您崩潰的錯誤。看到我的評論如下。

#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); 
}