析构函数分段故障链表

时间:2016-02-24 04:21:40

标签: c++ linked-list segmentation-fault dynamic-memory-allocation

所以,我上下搜索过论坛,要么找不到任何有助于我的东西,要么找不到任何足以让我把它与我遇到的问题联系起来的东西。我的程序存储点并将这些点保存在struct(LNode)中,该struct由我的Cluster类指向,创建一个链表。唯一的动态分配是Lnodes和Point对象的value数组。我对导致程序出现分段错误的原因感到茫然。我知道从运行调试器时,我的函数在我的Cluster.cpp文件的add函数中动态分配一个新的LNode时会发生这种情况。当函数进入退出并调用点析构函数时会发生这种情况。以下是我的文件的相关部分:

point.h

#include <iostream>

namespace Clustering {

class Point {
    unsigned int __id;
    int __dim;        // number of dimensions of the point
    double *__values; // values of the point's dimensions

    static unsigned int __idGen; // id generator

public:
    Point(int);
    Point(int, double *);

    // Big three: cpy ctor, overloaded operator=, dtor
    Point(const Point &);
    Point &operator=(const Point &);
    ~Point();

point.cpp

#include "Point.h"
#include <cmath>
#include <assert.h>

using namespace std;
using namespace Clustering;

namespace Clustering {

unsigned int Point::__idGen = 0;

Clustering::Point::Point(int i)
{
    __dim = i;
    __values = new double[__dim];
    for (int count = 0; count < __dim; ++count)
        __values[count] = 0.0;
    __id = __idGen++;
}

Point::Point(int i, double *pDouble)
{
    __dim = i;
    __values = pDouble;
    __id = __idGen++;
}

Point::Point(const Point &point)
{
    __dim = point.__dim;
    __values = new double[__dim];
    for (int count = 0; count < __dim; ++count)
        __values[count] = point.__values[count];
    __id = point.__id;
}

Point &Point::operator=(const Point &point)
{
    if (this == &point)
        return *this;
    else {
        __dim = point.__dim;
        for (int count = 0; count < __dim; ++count)
            __values[count] = point.__values[count];
        __id = point.__id;
    }
    return *this;
}

Point::~Point()
{
    std::cout << "This is the value " << &__values << std::endl;
    delete  [] __values;
}

Cluster.h

#include "Point.h"

namespace Clustering {

typedef struct LNode *LNodePtr;

struct LNode {

    Point point;
    LNodePtr next;
    LNode(const Point &p, LNodePtr n);

};

class Cluster {

    int __size;
    LNodePtr __points;

    //void __del();
    //void __cpy(LNodePtr pts);
    //bool __in(const Point &p) const;


public:
    Cluster();

    // The big three: cpy ctor, overloaded operator=, dtor
    Cluster(const Cluster &);
    Cluster &operator=(const Cluster &);
    ~Cluster();

    // Set functions: They allow calling c1.add(c2.remove(p));
    void add(const Point &);

    // Overloaded operators

    // Members: Subscript
    const Point &operator[](unsigned int index) const;

cluster.cpp

#include <cstdlib>
#include <assert.h>
#include "Cluster.h"

namespace Clustering{

LNode::LNode(const Point &p, LNodePtr n = nullptr) : point(0) {
    point = p;
    next = n;
}

Cluster::Cluster() {
    __size = 0;
    __points = nullptr;
}

Cluster::Cluster(const Cluster &cluster) {
    __size = cluster.__size;
    if(__size == 0)
        __points = nullptr;
    else{
        for(int count = 0; count < cluster.__size; ++count){
            add(cluster[count]);
        }
    }
}

Cluster &Cluster::operator=(const Cluster &cluster) {
    if(this == &cluster)
        return *this;
    else {
        for(int count = 0; count < cluster.__size; ++count){
            add(cluster[count]);
        }
    }
    return *this;
}

Cluster::~Cluster(){
    if(__points != nullptr){
        LNodePtr currPtr = __points;
        LNodePtr nextPtr = nullptr;
        while(currPtr != nullptr){
            nextPtr = currPtr->next;
            delete currPtr;
            currPtr = nextPtr;
        }
    }
    else
        assert(__size==0);
}
void Cluster::add(const Point &point) {
    Point p(point);
    LNodePtr insertPtr = new LNode(p, nullptr);
    LNodePtr prev = __points;
    LNodePtr next = __points;
    if(__points == nullptr) {
        __points = insertPtr;
        __size++;
    }
    else if(__points->next == nullptr){
         if (point < __points->point) {
            __points = insertPtr;
            __size++;
        }
        else
            __points->next = insertPtr;
    }
    else{
        while(next != nullptr && (prev->point < point && point >= next->point)){
            prev = next;
            next = next->next;
        }
        prev->next = insertPtr;
    }
}
 const Point &Cluster::operator[](unsigned int index) const {
    assert(__points != nullptr && index < __size);
    LNodePtr cursor = __points;
    for(int count = 0; count < index; ++count)
        cursor = cursor->next;
    return cursor->point;
}

主要是我使用的简单测试。

Cluster c1;
c1.add(Point(5));

非常感谢任何帮助,我对这种类型的结构相当新,并且已经在2天的时间内处理了这个错误。

2 个答案:

答案 0 :(得分:2)

Cluster::add函数中,您创建一个新的LNode,在LNode构造函数中,point对象构造为零大小的数组。这是允许的,但给出了未定义的行为。见C++ new int[0] -- will it allocate memory?。您已创建零大小的数组,但在Point::operator=构造函数的第一行中使用的LNode函数中,您永远不会为__values分配新内存,因此您正在复制5将值转换为零大小的数组。当发生这种情况时,谁知道你会覆盖什么。尝试使用valgrind或其他一些内存分析工具运行。这应该确定这个问题和其他任何问题。

答案 1 :(得分:0)

迈克尔覆盖了分段违规问题; add()方法中存在一个较小的逻辑问题:该方法永远不会更新insertptr-&gt; next,因此无论何时插入新节点,所有后续已存在的节点都将丢失。