使用 *this 时出现段错误
当我尝试从同一类的方法中访问类的成员时,我遇到了段错误,这对我来说根本没有意义。
我有 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;
}
...以及 Coord 继承的 Loc 类...
class Loc
{
public:
int x, y;
//Constructor
Loc(int xPos, int yPos) : x(xPos), y(yPos) {}
};
如注释所示,段错误发生在 Coord::getValidMoves() 中。如果单步执行代码到该点,然后监视 *this 或 x 或 this->x,我会收到“无法访问 0xbaadf00d 处的内存”的消息,
为什么会发生这种情况?我哪里搞砸了?我只是不明白尝试在方法中访问 *this 可能会导致段错误。
I'm getting a segfault when I try to access a member of a class from within a method of that same class, which does not make sense to me at all.
I have the Tree class:
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]);
}
}
}
}
}
...and the Coord class...
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;
}
... and the Loc class, from which Coord inheirits...
class Loc
{
public:
int x, y;
//Constructor
Loc(int xPos, int yPos) : x(xPos), y(yPos) {}
};
The segfault occurs in Coord::getValidMoves() as indicated by the comments. If step through the code to that point, then make a watch for *this or x or this->x, I get a "Cannot access memory at 0xbaadf00d"
Why is this happening? Where have I messed up? I just don't understand how trying to access *this in a method could possibly result in a segfault.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
您需要初始化
Coord::children
的元素。它们不保证为 NULL,因此在populateTree()
中,当您对每个子项进行 null 测试时,您将得到非 null 子项,尽管它们不会指向有效的坐标。当它们从队列中弹出时,您对无效的
Coord
调用getValidMoves()
,您将得到段错误。将
Coord
构造函数更改为:(您需要为
std::fill
添加#include
。请注意,会发生段错误尝试取消引用
this
时,因为这是您第一次尝试访问无效内存。You need to initialise the elements of
Coord::children
. They aren't guaranteed to be NULL, so inpopulateTree()
, when you do the null test on each child, you will get non-null children although they will not point to a validCoord
. When they are popped off the queue, and you callgetValidMoves()
on the invalidCoord
you'll get the seg-fault.Change the
Coord
constructor to:(you'll need to
#include <algorithm>
forstd::fill
.Note that the segfault occurs on the attempt to dereference
this
because that's the first time you try to access the invalid memory.当对无效(或失效)指针调用方法时,访问数据成员时出现段错误是一个常见问题。虽然该语言提供了对象和方法的抽象,但底层实现仍然具有函数和数据,其中方法是应用于数据的函数(代码)(隐式
*this
)。在调用方法之前检查指针是否有效(不为空,未释放),因为这肯定是问题所在:
在上面的代码中,所有错误大多数都会在标记为 [1] 的行处检测到
A segfault when accessing data members is a common problem when a method is called on an invalid (or invalidated) pointer. While the language provides the abstraction of objects and methods, the underlying implementation still has functions and data, where methods are functions (code) that applies to an data (implicit
*this
).Check that the pointers are valid (not null, not freed) before calling the method, as that is surely the problem:
In the code above, all errors will most be detected at the line marked as [1]
如果你让你的构造函数看起来像这样:
你的问题就会消失。您应该在构造函数中初始化所有数据成员。
问题是
children
将包含随机数据。它不会被初始化为 NULL,因此即使对于不存在的子节点,测试 currnode->children[i] != NULL 也不会为真。然后,您将调用这些不存在的子函数的成员函数,并且当这些成员函数运行时,它们将具有无效的this
指针。If you make your constructor look like this:
your problem will go away. You should initialize all your data members in the constructor.
The problem is that
children
will contain random data. It won't be initialized toNULL
, and so the testcurrnode->children[i] != NULL
will not be true even for non-existent children. You will then call member functions on these non-existent children and when those member functions run they will have an invalidthis
pointer.