当我尝试从同一个类的方法中访问类的成员时,我遇到了段错误,这对我来说根本没有意义。
我有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的内存”
为什么会这样?我搞砸了哪里?我只是不明白如何在方法中尝试访问*这可能会导致段错误。
答案 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
指针。