访问结构时出现段错误

时间:2016-03-29 03:36:22

标签: c++ struct segmentation-fault

我将整个代码放在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();
  }
}

问题仅在我尝试访问点时开始,我可以从该行实例访问其他属性而不会出现问题。我做错了什么?

编辑:我希望我提供了足够的信息,主要代码很长,并且与线路课程没什么关系,所以我不认为它是这样的相关的。

3 个答案:

答案 0 :(得分:4)

问题在于您的列表类。

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()?的 动臂

我不明白为什么你不能用一个漂亮而简单的DisplayFile取代整个std::list课程:

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
}

答案 1 :(得分:1)

问题可能来自你的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

答案 2 :(得分:1)

因为你没有初步化结构。

稍微改变一下构造函数

从此

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

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

这可能有所帮助。