c++ - Int 值急剧变化和段错误

标签 c++ class pointers linked-list segmentation-fault

我最近一直在尝试学习 C++,我正在努力制作一个没有交集的区间链表,但我遇到了一些非常奇怪的错误。在我第二次运行 reuinion 函数后,我的整数(从 get_bi 或 get_bs 获得)给出了一些非常荒谬的值。由于这些值会导致一些意外行为,因此我遇到了段错误。我认为这是问题的根源,但我不确定如何解决它们。我不认为我正在访问指向任何内容或任何导致它的指针。

#include <cstddef>
#include <iostream>

using namespace std;

class Uinter
    /*
     * Regrouping class for intervals (_Inter class) 
     * offering 3 different methods:
     *  "reunion(int bi, int bs)" -> Unites the interval pointed by "_tete"
     *                               with the one defined by [bi, bs]
     *  "printUinter()"           -> Prints the interval pointed by "_tete"
     *  "contient(int nb)"        -> Returns True if "nb" is present inside
     *                               the intervals, else False. 
     */
    {
        class _Inter
        /*
         * Class representing a single interval.
         * _bi stands for the lower limit of the interval.
         * _bs stands for the upper limit of the interval.
         */
        {
            int _bi, _bs;
            _Inter* _next;
        public:
            _Inter(int _bi, int _bs, _Inter* _next)
                {
                this->_bi = _bi;
                this->_bs = _bs;
                this->_next = _next;
                cout<<"_Inter created with bi, bs and _next = " << _bi << " , "<< _bs << " , " << _next <<endl;  
                };

                // Defining getters and setters for the interval.

            void set_bi(int value)
                {cout <<"setting bi = "<< _bi << endl;
                _bi = value;}

            void set_bs(int value)
                {cout <<"setting bs = "<< _bi << endl;
                _bs = value;}

            void set_next(_Inter* value)
                {_next = value;}

            int get_bi()
                {cout <<"getting bi = "<< _bi << endl;
                return _bi;}

            int get_bs()
                {cout <<"getting bs = "<< _bs << endl;
                return _bs;}

            _Inter* get_next()
                {cout << "next = " << _next << endl;
                return _next;}

            void print_self()
                {
                cout << "[" << this->_bi << ";" << this->_bs << "]" << endl;
                }
        };
        _Inter* _tete;
    public:
        Uinter(): _tete(nullptr){}
        void reunion(int bi, int bs)
            {
            if(_tete == nullptr)
                {cout << "Case 1" << endl;
                _Inter new_interval = _Inter(bi, bs, nullptr);
                _tete = &new_interval;
                cout << "_tete after Case 1 end = " << _tete << endl;
                cout << "_tete values after Case 1 end = " << _tete->get_bi() << " " << _tete->get_bs() << " " << _tete->get_next() << endl;
                cout << "_tete->get_next() == nullptr = " << (_tete->get_next() == nullptr) << endl;
                }
            else
                {cout << "Case 2" << endl;
                if(bi < _tete->get_bi())
                    {cout << "Case 2.1" << endl;
                    if (bs < _tete->get_bi())
                        {cout << "Case 2.1.1" << endl;
                        _Inter new_interval = _Inter(bi, bs, _tete);
                        _tete = &new_interval;
                        }

                    else if (bs > _tete->get_bs())
                        {cout << "Case 2.1.2" << endl;
                        _tete->set_bi(bi);
                        _Inter* temp;
                        temp = _tete->get_next();
                        while (temp != nullptr &&bs > temp->get_bs())
                            {cout << "Case 2.1.2 while" << endl;
                            temp = temp->get_next();
                            }
                        if (temp == nullptr)
                            {cout << "Case 2.1.2.1" << endl;
                            _tete->set_bs(bs);
                            _tete->set_next(nullptr);
                            }
                        else
                            {cout << "Case 2.1.2.2" << endl;
                            _tete->set_bs(temp->get_bs());
                            _tete->set_next(temp->get_next());
                            }
                        }

                    else if (bs > _tete->get_bi())
                        {cout << "Case 2.1.3" << endl;
                        _tete->set_bi(bi);
                        }                   
                    }
                else if (bi > _tete->get_bi())
                    {cout << "Case 2.2" << endl;
                    if (bi > _tete->get_bs())
                        {cout << "Case 2.2.1" << endl;
                        _Inter* temp;
                        temp = _tete->get_next();

                        while(temp != nullptr && bi > temp->get_bs())
                            {cout << "Case 2.2.1 while" << endl;
                            temp = temp->get_next();
                            }
                        if (temp == nullptr)
                            {cout << "Case 2.2.1.1" << endl;
                            _Inter new_interval = _Inter(bi, bs, nullptr);
                            temp->set_next(&new_interval);
                            }
                        else if (bi < temp->get_bi())
                            {cout << "Case 2.2.1.2" << endl;
                            if (bs < temp->get_bi())
                                {cout << "Case 2.2.1.2.1" << endl;
                                _Inter new_interval = _Inter(temp->get_bi(), temp->get_bs(), temp->get_next());
                                temp->set_bi(bi);
                                temp->set_bs(bs);
                                temp->set_next(&new_interval);
                                }

                            else if (bs > temp->get_bs())
                                {cout << "Case 2.2.1.2.2" << endl;
                                temp->set_bi(bi);
                                temp->set_bs(bs);
                                }

                            else if (bs > temp->get_bi())
                                {cout << "Case 2.2.1.2.3" << endl;
                                temp->set_bi(bi);
                                }                   
                            }
                        else if (bi > temp->get_bi())  // bi < temp.get_bs()
                            {cout << "Case 2.2.1.3" << endl;
                            if (bs > temp->get_bs())
                                {cout << "Case 2.2.1.2.1" << endl;
                                temp->set_bs(bs);
                                }
                            }
                        }
                    else if (bi < _tete->get_bs())
                        {// bi > tete->get_bi() et bi < _tete->get_bs()
                        cout << "Case 2.2.2" << endl;
                        _Inter* temp;
                        temp = _tete;
                        while (temp != nullptr && bs > temp->get_bs())
                            {cout << "Case 2.2.2 while" << endl;
                            temp = temp->get_next();    
                            }
                        if (temp == nullptr)
                            {cout << "Case 2.2.2.1" << endl;
                            _tete->set_bs(bs);
                            _tete->set_next(nullptr);
                            }
                        else
                            {// bi > tete->get_bi() et bi < _tete->get_bs() et bs < temp->get_bs()
                            cout << "Case 2.2.2.2" << endl;
                            if(bs > temp->get_bi())
                                {cout << "Case 2.2.2.2.1" << endl;
                                _tete->set_bs(temp->get_bs());
                                _tete->set_next(temp->get_next());
                                }
                            else
                                {cout << "Case 2.2.2.2.2" << endl;
                                _tete->set_bs(bs);
                                _tete->set_next(temp);
                                }
                            }
                        }
                    }
                }
            }
        void printUinter()
            {
            }

        bool contient(int nb);
    };


int main() 
{
    Uinter interval;
    interval.reunion(12, 23);
    interval.printUinter();
    cout << "___________" << endl;
    interval.reunion(24,36);
    interval.printUinter();
    cout << "___________" << endl;
    interval.reunion(0,11);
    interval.printUinter();
    cout << "___________" << endl;

    return 0;
}

这是我运行编译器时得到的结果(我真的不知道它代表什么,因为它只是说“运行失败”)。

> Case 1
> _Inter created with bi, bs and _next = 12 , 23 , 0
> _tete after Case 1 end = 0x23ca90 next = 0 getting bs = 23 getting bi = 12
> _tete values after Case 1 end = 12 23 0 next = 0
> _tete->get_next() == nullptr = 1
> ___________ Case 2 getting bi = -17000128 getting bi = -17000128 Case 2.2 getting bs = 3 Case 2.2.1 next = 0x1fefcb6c0
> 
> RUN FAILED (exit value 1, total time: 274ms)

我读到过运行调试器可能会有帮助,但是在 NetBeans 8.0.2 (gdb) 中运行调试器只会给我一个段错误并且没有关于它的真实信息,所以我不太确定如何修复它.它突出显示一行:

    int get_bs()
        {cout <<"getting bs = "<< _bs << endl;
        return _bs;}

但我不太确定我应该如何解释它,因为那条线上没有指针或任何东西。

Here is what I get on my debugger

最佳答案

你有一个名为 _tete 的类(class)成员:

        _Inter* _tete;

您使用“堆栈”分配对象(本地对象)的地址初始化类成员。

                _Inter new_interval = _Inter(bi, bs, nullptr);
                _tete = &new_interval;

一旦函数返回并且对象被重用,_tete 将不会为 NULL,而是指向一个无效的对象。

此外,_tete 未由 _Inter::_Inter() 初始化。


C++ 内存模型的完整描述超出了这个答案的范围,但足以说明一个对象只有在它存在时才有效。指向对象的指针仅在对象有效时才有效。本地对象仅在定义它的本地范围内有效。

Foo *a_ptr = NULL;
if (condition) {
    Foo a; // a is local to the statement block
    a_ptr = &a;
    //...
}          // a has been destructed (it no longer exists)
           // a_ptr points to an invalid object

如果你想创建一个对象并让它在创建它的范围之外继续存在,你需要使用某种动态内存分配。在 C++ 中,这可以通过使用 new 来完成。通常,如果一个对象是用 new 创建的,则需要用 delete 销毁它。因此,这种内存管理需要手动跟踪代码何时完成对象,以便可以应用适当的清理。

Foo *a_ptr = NULL;
if (condition) {
    a_ptr = new Foo(/*...*/);
    //...
}
delete a_ptr; // Note that delete does not set the argument to NULL

脚本语言通常使用某种垃圾收集工具和/或引用计数以自动方式处理此问题。 C++ 没有指定任何垃圾收集设施,但智能指针包含在标准 C++ 库中。当代码完成一个对象时,智能指针会自动跟踪,并确保在不再引用该对象时进行适当的清理。在这种情况下,_tete 似乎可以变成 unique_ptr

    std::unique_ptr<_Inter> _tete;
    //...
        _tete.reset(new _Inter(bi, bs, std::nullptr));

关于c++ - Int 值急剧变化和段错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29189109/

相关文章:

c++ - 使用 libxml2 解析包含无效字符的 XML 属性

class - 直接使用私有(private)属性与使用 Get 和 Let/Set

javascript - 从任何地方访问 Singleton

具有 asio get 方法成员的 C++ 对象

C++ 初始化指针随机崩溃应用程序?

c++ - OpenGL 纹理映射不起作用

javascript - 如何使用 C++ 插件中内置的 node.js 模块

c - 初始化从整数生成指针而不进行强制转换 - C

C++ 多维数组和指向指针表的指针

android - NDK 应用程序相当于 System.nanoTime() 吗?