【问题标题】:Destructor Segmentation Fault Linked List析构函数分段故障链表
【发布时间】:2016-06-06 05:09:29
【问题描述】:

所以,我在论坛上下搜索,要么没有找到任何对我有帮助的东西,要么没有找到任何有意义的东西来将它与我遇到的问题联系起来。我的程序存储点并将这些点保存在一个结构 (LNode) 中,该结构 (LNode) 由我的 Cluster 类创建一个链表所指向。唯一的动态分配是针对 Lnode 和 Point 对象的值数组。我不知道是什么导致我的程序出现分段错误。我从运行调试器中知道,当我的函数在我的 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;
}

集群.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;

集群.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 天的时间来处理这个错误。

【问题讨论】:

  • 您可能想了解std::unique_ptr。您在这里多次重新发明轮子,其中一些您不必先破坏旧的。还可以帮助您抵御 Point::Point(int i, double *pDouble) 即将到来的厄运。
  • 谢谢迈克尔,这正是问题所在!我不知道为什么我将 0 传递给初始化程序。愚蠢的错误!另外,谢谢拉尔斯。
  • 感谢 kfsone。我确实开始阅读独特的 ptr,它似乎是内存管理的更好选择,但我无法在这个项目中使用它。

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


【解决方案1】:

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

【讨论】:

    【解决方案2】:

    Michael 介绍了分段违规问题; add() 方法有一个较小的逻辑问题:该方法永远不会更新 insertptr->next,因此无论插入新节点,所有后续已经存在的节点都会丢失。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-01-29
      • 1970-01-01
      • 1970-01-01
      • 2018-02-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多