尝试在C++中使用 NULL 指针时不会发生分段错误



我定义了两个类:

template<class Datatype>
class Node
{
    public:
        Node()
        {
            next = NULL;
            prev = NULL;
        }
        Node* getNext()
        {
            return next;
        }
        Node* getPrev()
        {
            return prev;
        }
        Datatype* getData()
        {
            return &data;
        }
        void changeNext()
        {
            next = NULL;
        }
        void changeNext(Node& nextNode)
        {
            next = &nextNode;
        }
        void changePrev()
        {
            prev = NULL;
        }
        void changePrev(Node& prevNode)
        {
            prev = &prevNode;
        }
        Node* addNext(Node &);
        Node* addPrev(Node &);
        void nodeDel();
        void addData(Datatype &);
    private:
        Node* next;
        Node* prev;
        Datatype data;
};
template<class Datatype>
class Stack
{
    public:
        Stack() : node()
        {
            ;
        }
        int push(Datatype &);
        Datatype pop();
        Datatype* peek();
    private:
        Node<Datatype> node;
};

我试图做一些调试。我使用函数调用将数据包推送到此堆栈中:

template <class Datatype>
int Stack<Datatype>::push(Datatype &new_data)
{
    Node<Datatype> *pt_node = new Node<Datatype>;
    if (pt_node == NULL)
        return -1;
    Datatype *pt_data;
    pt_data = (this -> node).getData();
    pt_node -> addData(*pt_data);   
    (this -> node).addData(new_data);
    pt_node -> addNext(this -> node);
    cout << ((node.getNext())) << endl;
    return 0;
}

我打印出了节点的下一个指针。它应该是NULL的,因为它是堆栈中唯一的数据包,结果证明了这一点。调用此函数时的输出为 0。但是,我稍微更改了推送函数的cout指令:

cout << ((node.getNext()) -> getData()) << endl;

我尝试打印出下一个节点的数据。显然什么都不应该存在,因为该节点不存在,我已经证明node.getNext()返回0。奇怪的是分段错误没有发生在这里,它确实有一个输出0x8。我不知道这是怎么发生的。

getData返回指向成员的指针;因此它不需要取消引用this,只需为其添加偏移量即可。这就是为什么即使this为空也不会得到分段错误的原因。

当然,这仍然是未定义的行为。

取消引用 NULL 指针是未定义的行为,这实际上意味着任何事情都可能发生,它不能保证崩溃(尽管操作系统可能会为了自身安全而使您的应用程序崩溃)这是高度依赖于实现的,并且此类代码不应存在于您的应用程序中。

引用标准

注意:特别是,空引用不能存在于定义良好的 程序,因为创建此类引用的唯一方法是 将其绑定到通过取消引用空指针获得的"对象", 这会导致未定义的行为。如 9.6 中所述,参考 不能直接绑定到位域。——尾注

相关内容

  • 没有找到相关文章

最新更新