Int 值急剧变化和分段错误
Int values changing drastically and segmentation faults
我最近一直在努力学习 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;
}
这是我 运行 我的编译器得到的结果(我真的不知道它代表什么,因为它只是说 "Run failed")。
> 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;}
但我不太确定我应该如何解释它,因为那一行没有指针或任何东西。
您有一个 class 成员叫 _tete
:
_Inter* _tete;
您使用 "stack" 分配对象(本地对象)的地址初始化 class 成员。
_Inter new_interval = _Inter(bi, bs, nullptr);
_tete = &new_interval;
一旦函数returns和对象被重用,_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
脚本语言通常使用某种垃圾收集工具 and/or 引用计数以自动方式处理此问题。 C++ 没有指定任何垃圾收集设施,但智能指针包含在标准 C++ 库中。当代码完成一个对象时,智能指针会自动跟踪,并确保在不再引用该对象时进行适当的清理。在这种情况下,似乎 _tete
可以变成 unique_ptr
.
std::unique_ptr<_Inter> _tete;
//...
_tete.reset(new _Inter(bi, bs, std::nullptr));
我最近一直在努力学习 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;
}
这是我 运行 我的编译器得到的结果(我真的不知道它代表什么,因为它只是说 "Run failed")。
> 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;}
但我不太确定我应该如何解释它,因为那一行没有指针或任何东西。
您有一个 class 成员叫 _tete
:
_Inter* _tete;
您使用 "stack" 分配对象(本地对象)的地址初始化 class 成员。
_Inter new_interval = _Inter(bi, bs, nullptr);
_tete = &new_interval;
一旦函数returns和对象被重用,_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
脚本语言通常使用某种垃圾收集工具 and/or 引用计数以自动方式处理此问题。 C++ 没有指定任何垃圾收集设施,但智能指针包含在标准 C++ 库中。当代码完成一个对象时,智能指针会自动跟踪,并确保在不再引用该对象时进行适当的清理。在这种情况下,似乎 _tete
可以变成 unique_ptr
.
std::unique_ptr<_Inter> _tete;
//...
_tete.reset(new _Inter(bi, bs, std::nullptr));