2011-10-05 95 views
0

我一直在使用C++編寫項目,通常我不會在分段錯誤方面遇到太多麻煩,但我是C++的新手。基本上,我做了一個指向IntList的指針,並調用prepend()從指針創建一個IntList。問題是prepend被調用時,它被卡在頭文件的某處,justd退出。我不知道是什麼導致了這一點,gdb告訴我它只是卡在頭上。幫助將非常感激,就像提示或線索我做錯了什麼。謝謝。這是爲什麼導致分段錯誤?

IntList.h:

#ifndef _INTLIST_H 
#define _INTLIST_H 

#include <string> 
#include <cstring> 
using namespace std; 

class EmptyIntList; 

class IntList 
{ 
public: 
    static IntList *emptyList(); 
    //static IntList *fromString(string s);                                       

    virtual bool  isEmpty(); 
    IntList *prepend(int n); 
    virtual int  head(); 
    virtual IntList *tail(); 
    string toString(); 

    //  virtual int  length();                                        
    //  virtual IntList *append(IntList *lst);                                     

    //  virtual int  operator[](int n);                                      

    //  virtual ~IntList();                                          

protected: 
    IntList(); 
    IntList(IntList &); 
    //  const IntList &operator=(const IntList &);                                    
private: 
    int  data; 
    IntList *rest; 
}; 


IntList *operator+(IntList &lst1, IntList &lst2); 
ostream &operator<<(ostream &outStream, IntList *lst); 
ostream &operator<<(ostream &outStream, IntList &lst); 

#endif 

IntList.cpp:

#include "IntList.h" 
#include "EmptyIntList.h" 
#include <sstream> 

IntList::IntList(){} 

IntList *IntList::emptyList(){ 

    return ((IntList*)EmptyIntList::emptyList()); 

} 

bool IntList::isEmpty(){ 

    return false; 

} 

IntList *IntList::prepend(int n){ 

    IntList *x; 

    IntList y; 

    *x = y; 

    y.data = n ; 

    y.rest = x ; 

    return x; 

} 

int IntList::head(){ 

    return data; 

} 

IntList *IntList::tail(){ 

    return rest; 

} 

testIntList.cpp:

int main() 
{ 
    int n; 
    IntList *x; 
    n=6; 

    x->prepend(n); 
    // cout << x->toString();                                           
    return 0; 

} 

GDB步步​​:

8 int main() 
(gdb) step 
12 n=6; 
(gdb) 
14 x->prepend(n); 
(gdb) 
IntList::prepend (this=0x0, n=6) at IntList.cpp:30 
30 IntList y; 
(gdb) 
IntList (this=0x7fff93ecb3c0) at IntList.cpp:12 
12 IntList::IntList(){} 
(gdb) 
IntList::prepend (this=0x0, n=6) at IntList.cpp:32 
32 *x = y; 
(gdb) 
IntList::operator= (this=0x401650) at IntList.h:18 
18 { 
(gdb) 

Program received signal SIGSEGV, Segmentation fault. 
0x0000000000401361 in IntList::operator= (this=0x401650) at IntList.h:18 
18 { 
+0

你說你是C++新手?我會推薦[一本很好的C++入門書](http://stackoverflow.com/q/388242/46642)。是的,我對每個新手都說:) –

回答

0

任何尚未初始化的指針都有一個未定義的值,例如,它可能指向堆未分配區域中的隨機垃圾。對未分配的堆區域的任何解引用都是分段錯誤。

您需要使用new運算符來分配一些堆內存並獲取該內存的地址。 在主:

IntList *x; // IntList 
x = new IntList(); 

在前面加上:

IntList *x; 
x = new IntList(); // We now have no need for the local variable y 
x->data = n; 

它看起來像你想用地址的操作,在y以點X,即x=&y但這將返回一個指向垃圾。任何局部變量都在堆棧中分配,並在函數返回時立即解除分配。由於內存可能會被快速重新分配給其他內容,因此在指向內存的範圍之後,切勿保留指向堆棧內存的指針,以防止崩潰造成神祕行爲。

查找刪除操作符。

0

下面只是定義了一個指針,而不是malloc內存,所以它指向內存中的一個隨機地址: IntList * x;

當您嘗試爲其分配值「y」時,程序崩潰。

0

我明白了兩件事。

1)主要是,你沒有分配一個IntList,只是一個IntList *指向垃圾。當你調用x-> prepend時,你正在使用未初始化的內存。在調用方法之前,您需要一個具體的對象。

2)你的prepend方法創建一個locaion IntList,並返回它,這是一個否定的。你回到那個曾經在棧上,現在不再有效的對象(雖然它可能工作,有時,有趣的事情,是不確定的行爲。)

+0

'prepend'的退貨很好。 'prepend'中的UB與main相同:'x'未初始化。 –

1
IntList *x; 

這是未初始化的,所以是值它指向。