使用*这时的Segfault

时间:2011-01-22 00:05:07

标签: c++ debugging segmentation-fault

当我尝试从同一个类的方法中访问类的成员时,我遇到了段错误,这对我来说根本没有意义。

我有Tree类:

class Tree
{

public:

Coord* root;

Tree(int x, int y)
{
    root = new Coord(x, y);
    populateTree();
}

void populateTree()
{
    queue<Coord*> nodes;
    nodes.push(root);

    while (nodes.size() > 0)
    {
        Coord* currnode = nodes.front();
        nodes.pop();

        if ( !(currnode->getValidMoves()) )
        {
            return;
        }

        else
        {
            for (int i = 0; i < MAX_CHILDREN_PER_COORD; i++)
            {
                if (currnode->children[i] != NULL)
                {
                    nodes.push(currnode->children[i]);
                }
            }
        }
    }
}

......和Coord班......

class Coord : public Loc
{
    public:

    Coord(int xPos, int yPos);

    Coord* children[MAX_CHILDREN_PER_COORD];


    bool getValidMoves();


    bool operator==(Coord coord);
    bool operator==(Loc loc);

};

Coord::Coord(int xPos, int yPos) : Loc(xPos, yPos) {}


bool Coord::getValidMoves()
{
    //This line segfaults
    Coord test = *this;

    //Global boolean method. Checks found
    if (!foundTrue())
    {
        for (int i = 0; i < MAX_CHILDREN_PER_COORD; i++)
        {
            //If the above segfaulting line is commented out, this is the first place that segfaults
            int newX = x + knightPositions[i].x;
            int newY = y + knightPositions[i].y;

            if ( !(newX > GRID_X || newX < 0 || newY > GRID_Y || newY < 0) )
            {
                //knightPositions is a Loc array of length MAX_CHILDREN_PER_COORD
                children[i] = new Coord(x + knightPositions[i].x, y + knightPositions[i].y);
                //Global 2d array of ints. Gets checked by foundTrue()
                found[x + knightPositions[i].x][y + knightPositions[i].y] = true;
            }
        }

        return true;
    }

    else
    {
        return false;
    }

    //Otherwise, just leave it as a blank array
}


bool Coord::operator==(Coord coord)
{
    return coord.x == x && coord.y == y;
}

bool Coord::operator==(Loc loc)
{
    return loc.x == x && loc.y == y;
}

...和Loc类,Coord inheirits ...

class Loc
{
    public:
        int x, y;

        //Constructor
        Loc(int xPos, int yPos) : x(xPos), y(yPos) {}
};

段落错误发生在Coord :: getValidMoves()中,如注释所示。如果逐步执行代码,那么请注意* this或x或this-&gt; x,我得到一个“无法访问0xbaadf00d的内存”

为什么会这样?我搞砸了哪里?我只是不明白如何在方法中尝试访问*这可能会导致段错误。

3 个答案:

答案 0 :(得分:4)

您需要初始化Coord::children的元素。它们不能保证为NULL,因此在populateTree()中,当您对每个子进行空测试时,您将获得非空子项,尽管它们不会指向有效的Coord。当它们从队列中弹出,并且您在无效getValidMoves()上调用Coord时,您将获得seg-fault。

Coord构造函数更改为:

Coord::Coord(int xPos, int yPos) : Loc(xPos, yPos)
{
    std::fill( children, children + MAX_CHILDREN_PER_COORD, NULL );
}

(对于#include <algorithm>,您需要std::fill

请注意,在尝试取消引用this时会发生段错误,因为这是您第一次尝试访问无效内存。

答案 1 :(得分:1)

访问数据成员时的段错误是在无效(或无效)指针上调用方法时的常见问题。虽然该语言提供了对象和方法的抽象,但底层实现仍然具有函数和数据,其中方法是应用于数据的函数(代码)(隐式*this)。

在调用方法之前检查指针是否有效(非空,未释放),因为这肯定是问题所在:

struct test {
   int x;
   void foo( int y ) {
      x = y;       // [1]
   }
};
int main() {
   test *p = 0;
   //p->foo();     // segfault in x=y above: this == 0
   p = new test;
   p->foo();
   delete p;
   // p->foo();    // undefined behavior, can be a segfault or not
   p = reinterpret_cast<test*>( "This is a literal" );
   p->foo();       // undefined behavior, probably segfault
                   // writing to read-only memory (this depends on compiler/environment)
}

在上面的代码中,所有错误都将在标记为[1]

的行中检测到

答案 2 :(得分:0)

如果你让你的构造函数看起来像这样:

Coord::Coord(int xPos, int yPos) : Loc(xPos, yPos)
{
    for (int i = 0; i < MAX_CHILDREN_PER_COORD; ++i) {
        children[i] = NULL;
    }
}

你的问题会消失。您应该在构造函数中初始化所有数据成员。

问题是children将包含随机数据。它不会被初始化为NULL,因此即使对于不存在的孩子,测试currnode->children[i] != NULL也不会成立。然后,您将在这些不存在的子节点上调用成员函数,当这些成员函数运行时,它们将具有无效的this指针。