在尝试回答stackexchange上的问题时,我试图查看这段代码:
#include <iostream>
using namespace std;
struct Node {
int key;
Node *leftnode;
Node *rightnode;
string value;
Node(int tkey, const std::string& tvalue) : leftnode(nullptr), rightnode(nullptr), key(tkey), value(tvalue) {}
};
Node root_node(1, "Node #1"); // Binary search tree
string inline query_bst(const int key) {
Node *cur_node = &root_node;
while (cur_node != NULL) {
if (key == cur_node->key) {
return cur_node->value;
}
if (key < cur_node->key) { /* value already returned, no need for else */
cur_node = cur_node->leftnode;
} else {
cur_node = cur_node->rightnode;
}
}
return ""; // Return empty string if not found
}
void inline insert_bst(int key, string value) {
Node *cur_node;
Node *next_node = &root_node;
// Search through bst for key
while (next_node != NULL) {
cur_node = next_node;
if (key < cur_node->key) {
next_node = cur_node->leftnode;
} else {
next_node = cur_node->rightnode;
}
}
Node new_node(key, value);
next_node = &new_node;
if (key < cur_node->key) {
cur_node->leftnode = next_node;
} else {
cur_node->rightnode = next_node;
}
}
int main() {
root_node.key = 1;
insert_bst(2, "Node #3");
insert_bst(3, "Node #4");
cout << query_bst(3) << '\n' << query_bst(4);
}
对我来说,这个程序编译,但崩溃了。我搜索了这个的原因,并推断(希望是正确的)在函数“insert_bst()”中创建一个名为“new_node”的变量,然后为该变量的地址指定一个指针。但是,new_node var具有自动持续时间,因此在函数执行结束时会被销毁。因此,在第二次调用insert_bst()期间,当程序尝试访问插入节点的键/值时,将重新获取垃圾值(这是我使用调试器确认的),这会破坏程序。 那么为什么这段代码可以在其他平台上正常工作呢?
我的测试是在Windows 7 x64上,在Code :: Blocks 16.01和CLion上使用g ++完成的。
代码工作的平台:Mac OS X Yosemite Clion,也是g ++
答案 0 :(得分:2)
正如您所推断的那样,该函数正在创建一个本地对象并将其添加到BST。当函数返回时本地对象被销毁时,我们现在有一个悬空指针并使用它是未定义的行为。
由于未定义的行为意味着程序的行为未定义。它可能会运行,崩溃,变得自我意识并将自己命名为天网或其他任何东西。
正如MikeCAT指出的那样,我们可以通过使用new
来使节点持久化并摆脱悬空指针问题来摆脱这种未定义的行为。