访问结构时出现 Seg 错误

Seg fault when accessing a struct

本文关键字:Seg 错误 结构 访问      更新时间:2023-10-16

我把整个代码放在github上:https://github.com/marianatuma/CG

我有一个名为 point 的结构,用 line.h 声明,以及一条类线,它有两个点,开始和结束。编辑:我之前没有添加它,但Line继承自GraphObj。 graphObj.h

class GraphObj {
private:
    type t;
    std::string name;
public:
    GraphObj(type t, std::string name);
    type getType();
    std::string getName();
};

line.h

#ifndef LINE_H
#define LINE_H
struct point {
    double x;
    double y;
};
class Line {
private:
    point start;
    point end;
public:
    Line(type t, std::string name) : GraphObj(t, name) {};
    void setStart(double x, double y);
    void setEnd(double x, double y);
    point getStart();
    point getEnd();
};
#endif

line.cpp

#include "line.h"
void Line::setStart(double x, double y) {
    this->start.x = x;
    this->start.y = y;
}
void Line::setEnd(double x, double y) {
    this->end.x = x;
    this->end.y = y;
}

point Line::getStart() {
    return start;
}
point Line::getEnd() {
    return end;
}

当我尝试访问这些点中的任何一个时,我总是遇到分段错误。我试着把它们公开,但没有用。我也尝试使用吸气剂,但它也没有用。以下是我初始化它们的方式:

该线位于称为显示文件的线列表中,将与 cairo 一起使用以绘制它们。

displayFile.h

#ifndef DISPLAYFILE_H
#define DISPLAYFILE_H
#include <list>
#include "graphObj.h"
class DisplayFile {
private:
    std::list<GraphObj*>* objectList;   
    std::list<GraphObj*>::iterator it;
    int size;
public:
    DisplayFile();
    void add(GraphObj* g);
    GraphObj* getNextObject();
    void resetIterator();
    int getSize();
};
#endif

displayFile.cpp

#include "displayFile.h"
DisplayFile::DisplayFile() {
    this->objectList = new std::list<GraphObj*>();
    this->it = objectList->begin();
    this->size = 0;
}
void DisplayFile::add(GraphObj* g) {
    std::list<GraphObj*>::iterator tempIt;
    tempIt = objectList->begin();
    this->objectList->insert(tempIt, g);
    this->size++;
}
GraphObj* DisplayFile::getNextObject() {
    return *++it;
}
void DisplayFile::resetIterator() {
    it = objectList->begin();
}
int DisplayFile::getSize() {
    return size;
}

DisplayFile 返回一个 GraphObj 而不是 objectList,所以它必须自己遍历 objectList,因此需要 resetIterator(所以当主代码遍历列表时,它会将迭代器重置到列表的开头,但到目前为止我还没有在任何地方调用此方法(。main.cpp中使用 Line 实例的代码如下:

static void do_drawing(cairo_t *cr)
{
  /* not using these right now
  cairo_set_source_rgb(cr, 0, 0, 0);
  cairo_set_line_width(cr, 0.5);
  */
  int size = df->getSize(); //df is the list
  for(int i = 0; i < size; i++) {
    Line* g = df->getNextObject();
    point start = g->getStart();
  }
}
问题

仅在我尝试访问点时开始,我可以毫无问题地从该线实例访问其他属性。我做错了什么?

编辑:我希望我提供了足够的信息,主代码很长,与行类没有太大关系,所以我认为它无关紧要。

问题出在您的列表类上。

class DisplayFile {
private:
    std::list<GraphObj*>* objectList;   // Why not just a list<GraphObj*>
    std::list<GraphObj*>::iterator it;  // Why use this?
    int size;                           // WHY manually keep track of a STL container size?
public:
    DisplayFile();
    void add(GraphObj* g);
    void resetIterator();
    int getSize();
};

在实现文件中:

GraphObj* DisplayFile::getNextObject() {
    return *++it;
}

正如我已经评论过的:这是赢家...想一想,如果it已经碰巧是列表中的最后一个元素,并且您要求getNextObject()怎么办?繁荣


我不明白为什么你不能用一个漂亮而简单的std::list替换整个DisplayFile类:

std::list<GraphObj*> objectList;
// I would also advice to change to smart pointers here
// for example: std::list<std::shared_ptr<GraphObj> > objectList;
// or           std::list<std::unique_ptr<GraphObj> > objectList;

然后,您只需使用 STL 方法处理列表:

前面添加一个项目:(为了简单起见,让我们假设GraphObj有一个默认构造函数(

GraphObj* g = new GraphObj();
objectList.push_front(g);
// If you change to smart pointers:
// objectList.push_front(std::make_shared<GraphObj>());
// or
// objectList.push_front(std::make_unique<GraphObj>());

获取列表大小:

objectList.size();

遍历列表:

for (std::list<GraphObj*>::const_iterator it = objectList.begin();
    it != objectList.end();
    ++it)
{
    point start = (*it)->getStart();
    // or whatever you need to do here
}

或者更好的范围:

for (const auto & graphObj : objectList)
{
    point start = graphObj->getStart();
    // or whatever you need to do here
}

因为你没有启动结构。

稍微更改构造函数

由此

Line(type t, std::string name) : GraphObj(t, name) {};

Line(type t, std::string name) : GraphObj(t, name) , start(),end() {};

这可能会有所帮助。

问题可能来自您的getStart和getEnd,因为它们返回一个点,这将创建您的起点或终点的副本(我认为(,即不使用行中的点而是副本。这通常没什么大不了的,但如果你想改变一个 x 或 y 值并让新的值坚持下去,你需要引用原始点 x 和 y 值。试试这个,改变

point getStart();
point getEnd();

point *getStart() { return &start; }
point *getEnd()   { return &end;   }

并在您的do_drawing(cairo_t *cr(更改

point start = g->getStart();

point *start = g->getStart();
start->x = value;        // or
double value = start->x; // or however you want to use start