将一个指针指向另一个指针时的Segfault

时间:2009-12-09 21:00:39

标签: c++ pointers segmentation-fault

我的大脑从来没有真正掌握链表和指针的细节,但我正在尝试用一些C ++任务来帮助朋友。 (在我再进一步之前,是的,有std :: list但我正在寻找一个学术答案,也许会让链接列表对他和我自己更容易理解。)

我们需要做的是根据用户输入生成对象的链接列表(Employee对象),然后将该信息显示给用户。每当我尝试将对象分配到链接列表容器时,就会发生段错误。

我有以下链接列表对象:

class LinkedListContainer {
    private:
        Employee *emp;
        LinkedListContainer *next;

    public:
        Employee getEmployee() { return *emp; }

        void setEmployee(Employee *newEmp) {
            *emp = *newEmp // This is what is causing the segfault
        }

        LinkedListContainer getNext() { return *next; }

        void setNext(LinkedListContainer *newContainer) {
            *next = *newContainer;
        }
}

我确信我做的事情非常糟糕。

7 个答案:

答案 0 :(得分:5)

查看您的班级,似乎没有指针emp设置为指向实际对象的位置。

这一行:

*emp = *newEmp;

newEmp指向的对象的值分配给emp指向的对象。除非两个指针都指向有效对象,否则代码将具有未定义的行为。

您最好将emp作为Employee对象,而不是指向需要手动管理指向对象生命周期的对象的指针。

这假定您的LinkedListContainer类是拥有Employee的节点。

另一方面,当你这样做时:

*next = *newContainer;

从命名我会假设您只想将下一个指针指向您可能想要做的另一个LinkedListContainer

next = newContainer;

因为这会将指针的值赋给变量next

当你设计你的类并使用指针时,你需要清楚,哪些对象拥有哪些其他对象,并确保你适当地管理它们的生命周期。

答案 1 :(得分:2)

*emp = *newEmp;

应该是:

emp = newEmp;

这样你就可以指定指针,而不是指针指向的对象。

答案 2 :(得分:1)

您的emp指针未初始化,因此当您尝试在*emp中取消引用它(setEmployee())时,您尝试访问不属于您的内存(因此会出现段错误)

你可能最好按值保持Employee(假设它不是多态的)并通过const引用传递setEmployee一个Employee对象:

class LinkedListContainer {
  Employee emp;

  // ...

  void setEmployee(const Employee& newEmp) {
    emp = newEmp;
  }

  // ...
};

当然,您还需要调整其他成员函数,以反映使用值与指针的对比。

祝你好运!

答案 3 :(得分:0)

*emp = *newEmp

你不想这样做 - 事实上,你根本不想取消引用任何指针。

emp = newEmp

答案 4 :(得分:0)

默认情况下,\ temp是指向无处的指针。通过写作

*emp = *newEmp;

您尝试将newEmp的内容分配给emp所指向的任何内存位置。如上所述,emp指向无处,所以你在这里取消引用一个NULL指针,这会导致分段错误。

如果你的容器要包含一个完整的Employee,你最好将emp声明为Employee类型(不是指向Employee的指针)。然后

emp = *newEmp;

会起作用,虽然我不太确定这是否只需要修复你的LinkedListContainer。

答案 5 :(得分:0)

您遇到的一个问题是由于访问指针时的前导*。 *告诉编译器在访问指针时,不是读取指针所指向的地址,而应该读取指针所指向的位置的值。

一个例子是变量就像拥有价值观的房屋。指针就像房子上的地址。通常,当编译器读取指针时,它只能看到地址。当你把指针放在*前面时它会告诉编译器查看“house”里面的值来提取其中的值。当您指定新地址时,您不想使用*,否则您正在复制值而不是地址。

所以你要做的事情就是在setNext中,例如:

next = newContainer;

答案 6 :(得分:0)

以前的答案解释了分段错误的原因。无论如何,如果您需要该样本供学术使用,那么恕我直言,您忘记了课堂成员的初始化。第二个问题是内存管理 - 谁分配/释放这些对象?在你的样本中也没有构造函数,也没有析构函数:)

你的课程可能如下所示:

class LinkedListContainer 
{    
    public:        
        LinkedListContainer()
            : d_emp( 0 ) 
            , d_next( 0 )
        {
        }

        bool isValid() const
        {
            const bool result = ( d_emp != 0 );
            return result;
        }

        const Employee& getEmployee() const
        { 
            assert( isValid() );
            return *d_emp; 
        }        

        void setEmployee( Employee* emp ) 
        {            
            d_emp = emp;
        }        

        LinkedListContainer* getNext() 
        { 
            return d_next; 
        }        

        void setNext( LinkedListContainer* next )
        {            
            d_next = next;        
        }

    private:        
        Employee* d_emp;        
        LinkedListContainer* d_next;    

};

如果您不想打扰Employee对象的内存管理,那么只需使用boost库中的shared_ptr。

typedef boost::shared_ptr< Employee > SmartEmployee;

class LinkedListContainer 
{    
    public:        
        LinkedListContainer()
            : d_next( 0 )
        {
        }

        bool isValid() const
        {
            return d_emp;
        }

        const Employee& getEmployee() const
        { 
            assert( isValid() );
            return *d_emp; 
        }        

        void setEmployee( SmartEmployee emp ) 
        {            
            d_emp = emp;
        }        

        LinkedListContainer* getNext() 
        { 
            return d_next; 
        }        

        void setNext( LinkedListContainer* next )
        {            
            d_next = next;        
        }

    private:        
        SmartEmployee d_emp;        
        LinkedListContainer* d_next;    

};