析构函数分段错误链表



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

点.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();

点.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;

群集.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 天了。

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

Michael 介绍了分割冲突问题;add() 方法中有一个较小的逻辑问题:该方法从不更新 insertptr->next,因此无论在哪里插入新节点,所有后续已经存在的节点都将丢失。

最新更新