Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/153.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ main()函数的意外返回值_C++_Linked List - Fatal编程技术网

C++ main()函数的意外返回值

C++ main()函数的意外返回值,c++,linked-list,C++,Linked List,我正在使用双链接列表。每个函数都运行良好,但在main()的末尾,它会暂停几秒钟并返回意外的随机值 起初,我认为这是由report()函数引起的,因此我在末尾又添加了一个add()函数,但没有修复任何问题。我怀疑这是内存释放问题,但我看不出某个对象在哪里被预释放。 (使用代码::Blocks 17.12编译) 这是我的.cpp文件(一体机): #包括 使用名称空间std; 类型定义结构元素{ 元素(){ 数据=0; next=0; prev=0; } ~element(){ 删除下一步; 删除上

我正在使用双链接列表。每个函数都运行良好,但在main()的末尾,它会暂停几秒钟并返回意外的随机值

起初,我认为这是由report()函数引起的,因此我在末尾又添加了一个add()函数,但没有修复任何问题。我怀疑这是内存释放问题,但我看不出某个对象在哪里被预释放。 (使用代码::Blocks 17.12编译)

这是我的.cpp文件(一体机):

#包括
使用名称空间std;
类型定义结构元素{
元素(){
数据=0;
next=0;
prev=0;
}
~element(){
删除下一步;
删除上一页;
cout-prev;
}
删除尾部;
cout数据;
如果(ls.head==0){//empty
ls.head=新元素;
ls.水头=温度;
}否则{
如果(ls.tail==0){//1-项列表
ls.tail=新元素;
ls.tail=温度;
ls.head->next=ls.tail;
ls.tail->prev=ls.head;
}
否则{
temp->prev=ls.tail;
ls.tail->next=温度;
ls.tail=温度;
}
}
}
作废报告(){

如果(ls.head==0)不能第一点:元素将被类
doublylinkedlist
解除分配,因此解除类
元素中的元素将导致双重解除分配。
因此,应该从lass
元素的析构函数中删除两条
delete
语句

    ~element(){
        /* remove them */
        //delete next;
        //delete prev;
        cout << "element destructed" << endl;
    }
最后一个元素将由
delete tail;
释放,因此此代码看起来很复杂,但应该可以

额外要点:这些代码段

        ls.head = new elem;
        ls.head = temp;

正在通过分配元素并立即丢弃它们而导致内存泄漏。 您应该删除额外的分配

        /* remove this */
        //ls.head = new elem;
        ls.head = temp;


除非您使用的是
std::shared_ptr
或类似的构造,否则每个对象都需要有另一个对象,即它的所有者并负责解除分配它。您的代码需要有明确的所有权转移语义(例如,函数
createNode()
希望其调用者破坏节点)

在您的代码中,列表和每个元素都会删除节点。这意味着所有内容都会被删除两次(或更多)。在您的特定情况下,这是销毁
doublylinkedlist
的事件序列:

  • 双链接列表
    删除其第一个元素
  • 第一个元素的析构函数删除其前一个元素,该值为null,因此无效
  • 第一个元素的析构函数删除下一个元素(第二个元素)
  • 第二个元素的析构函数删除其前一个元素(第一个元素)
  • 第一个元素的析构函数删除其前一个元素,该值为null,因此无效
  • 第一个元素的析构函数删除下一个元素(第二个元素)
  • 这个无限循环最终会导致堆栈溢出。请注意,这并不能保证是事件的精确序列,因为删除一个对象两次是未定义的行为,因此可能会发生任何事情

    简单的修复方法是删除
    元素
    析构函数,并让列表负责所有元素的生存期。 您还应该修改
    doublylinkedlist
    析构函数,因为它将尝试取消对最后一个元素上的空指针的引用,您也不需要删除
    tail
    ,因为它应该已经被删除。例如:

    ~doublylinkedlist(){
        while(head!=0) {
            auto temp = head;
            head = head->next;
            delete temp;
        }
    }
    
    您还应确保遵守)。一种方法是使用智能指针,例如使用
    unique\ptr
    s您的代码可能如下所示:

    #include <iostream>
    #include <memory>
    using namespace std;
    
    typedef struct element {
        element() {
            data = 0;
            next = nullptr;
            prev = nullptr;
        }
        ~element() {
            cout << "element destructed" << endl;
        }
        int data;
        std::unique_ptr< element > next;
        element* prev;
    } elem;
    
    typedef struct doublylinkedlist {
        doublylinkedlist() {
            head = 0; tail = 0;
        }
        ~doublylinkedlist() {
            std::cout << "list destructed\n";
        }
    
        std::unique_ptr< elem > head;
        elem* tail;
    } doublyll;
    
    doublyll ls;
    
    void add() {
        std::unique_ptr<elem> temp(new elem());
        cout << "Enter an integer: ";
        cin >> temp->data;
    
        if (ls.head == nullptr) {//empty
            ls.head = std::move(temp);
        }
        else {
            if (ls.tail == nullptr) {  //1-item list
                ls.head->next = std::move(temp);
                ls.tail = ls.head->next.get();
                ls.tail->prev = ls.head.get();
            }
            else {
                temp->prev = ls.tail;
                ls.tail->next = std::move(temp);
                ls.tail = ls.tail->next.get();
            }
        }
    }
    
    void report() {
        if (ls.head == 0) cout << "List is empty!" << endl;
        else {
            elem *temp = ls.head.get();
            do {
                cout << temp->data << endl;
                temp = temp->next.get();
            } while (temp != 0);
        }
    }
    
    int main() {
        report();
        add();
        add();
        add();
        report();
        add();
        return 0;
    }
    

    一些元素将被
    双链接列表
    元素
    多次删除,但应该还有一些问题,因为从
    元素
    析构函数中删除
    删除
    语句并没有消除分段错误。
    ls.head=new elem;ls.head=temp;
    Oh,内存泄漏。。。(同样的错误也使用了<代码> ls。尾<代码>),这不解决这个问题,但是在C++中,你不必做那个<代码> TyPufFr.{…} elm;< /Cord>舞曲。<代码> StuttELEM{};工作很好。或者只使用<代码> Stutt元素{}…;
    忘记缩写。
    0xc0000fd
    不是一个随机数,它意味着有一个堆栈overflow@AlanBirtles非常感谢您告诉我这一点。结果表明,返回值
    0xc0000fd
    是由于访问空指针引起的,这是由于我在doublyll解构器中的哑代码:
    delete head->prev;
    造成的。关于另外一点,我是这样想的:temp是在add()函数中声明的,因此在退出add()函数之前,~elem()解构器会解构它,所以我分配了ls.head和ls.tail,因为它们的作用域是全局的。我弄错了吗?@xceeded
    add()
    函数在
    元素
    类之外,因此
    ~elem()
    解构器不会影响
    add()
    函数中的局部变量。指针
    temp
    将在退出
    add()时释放
    函数,但指针分配给该函数的空间在该时间不会被释放,
    ls.head
    ls.tail
    已作为
    ls
    的一部分分配给
    ls.head=new elem;
    不是分配
    ls.head
    而是分配另一个空间并将其位置分配给
    ls.head
    。等等,我f A:“
    ls.head
    指向
    temp
    ”,B:“
    temp
    在退出
    add()
    ”时被删除,C:“删除对象后取消引用指针的程序可能会产生不可预测的结果或崩溃”(),那么为什么我的程序仍然工作?
    temp
    在退出
    add()时被删除)
    ,但是
    temp
    所指向的内容(通过
    新元素创建的内容)不会被删除
    
            /* remove this */
            //ls.head = new elem;
            ls.head = temp;
    
                /* remove this */
                //ls.tail = new elem;
                ls.tail = temp;
    
    ~doublylinkedlist(){
        while(head!=0) {
            auto temp = head;
            head = head->next;
            delete temp;
        }
    }
    
    #include <iostream>
    #include <memory>
    using namespace std;
    
    typedef struct element {
        element() {
            data = 0;
            next = nullptr;
            prev = nullptr;
        }
        ~element() {
            cout << "element destructed" << endl;
        }
        int data;
        std::unique_ptr< element > next;
        element* prev;
    } elem;
    
    typedef struct doublylinkedlist {
        doublylinkedlist() {
            head = 0; tail = 0;
        }
        ~doublylinkedlist() {
            std::cout << "list destructed\n";
        }
    
        std::unique_ptr< elem > head;
        elem* tail;
    } doublyll;
    
    doublyll ls;
    
    void add() {
        std::unique_ptr<elem> temp(new elem());
        cout << "Enter an integer: ";
        cin >> temp->data;
    
        if (ls.head == nullptr) {//empty
            ls.head = std::move(temp);
        }
        else {
            if (ls.tail == nullptr) {  //1-item list
                ls.head->next = std::move(temp);
                ls.tail = ls.head->next.get();
                ls.tail->prev = ls.head.get();
            }
            else {
                temp->prev = ls.tail;
                ls.tail->next = std::move(temp);
                ls.tail = ls.tail->next.get();
            }
        }
    }
    
    void report() {
        if (ls.head == 0) cout << "List is empty!" << endl;
        else {
            elem *temp = ls.head.get();
            do {
                cout << temp->data << endl;
                temp = temp->next.get();
            } while (temp != 0);
        }
    }
    
    int main() {
        report();
        add();
        add();
        add();
        report();
        add();
        return 0;
    }
    
    void add() {
        std::unique_ptr<elem> temp(new elem());
        cout << "Enter an integer: ";
        cin >> temp->data;
        if (!cin || temp->data > 100) {
           cout << "invalid input value\n";
           return; // temp is automatically deleted here
        }
        ...
    }