导致分段错误的简单字符串分配?
Simple string assignment causing a segmentation fault?
我通过很多 classes 跟踪了这个问题,令我惊讶的是,这个错误的根源是一个简单的 std::string = std::string
操作。
我不会post整个代码,只是按顺序执行的函数。我仍然认为 SO 标准的代码太多,但我看不到其他选择。
一些上下文注释:
- OrderedPair 是 public 结构
{ int y, int x }
,位于单独的 lib.inc
文件中。
- 前导下划线标记函数头中声明的变量
- 末尾下划线标记一个 class 成员变量
ncefm.cc -- 基本上是主文件
std::vector<std::string> juststring = {"teststring", "another string", "foobar"};
List* list0 = new List(w0_, juststring); // Source of the error
list.cc -- 这里调用了构造函数List()
忽略可选变量,反正不会调用它们
List::List(Frame* const _parent, std::vector<std::string> &_list,
const OrderedPair &_pos = {0, 0}, const unsigned int &_spacing = 1,
const unsigned int &_maxsize = 0) {
pos_ = _pos;
size_ = _list.size();
spacing_ = _spacing;
maxsize_ = _maxsize;
parent_ = _parent;
Fill(_list); //Source of the error
Redraw();
parent_->AddWidget(this);
}
list.cc -- 成员函数Fill()
list_是std::vector
类型的成员变量
void List::Fill(std::vector<std::string> &_list) {
for (unsigned int loop = size_; loop < (size_ + _list.size()); loop++) {
list_.push_back(new Label(parent_, _list[loop], {pos_.y + (loop * spacing_),
pos_.x}, maxsize_)); // source of the error (the constructor Label() )
}
}
label.cc -- 这里调用了构造函数 Label()
Label::Label(Frame* const _parent, std::string &_text,
const OrderedPair &_pos = {0,0}, const unsigned int &_maxsize = 0) {
pos_ = _pos;
maxsize_ = _maxsize;
parent_ = _parent;
SetText(_text); // Source of the error
parent_->AddWidget(this);
}
list.cc -- 成员函数SetText()
我们终于到了,错误的来源是...
void Label::SetText(std::string& _text) {
if (maxsize_ != 0 && _text.length() > maxsize_) _text.resize(maxsize_);
text_ = _text; // THIS?!
size_ = text_.length();
Redraw();
}
如果我只是注释掉这一行,错误就会消失,
当然,这会破坏功能。
text_.assign(_text);也不行。
label.h -- 显示头文件和一些变量的定义 text_
class Label {
private:
OrderedPair pos_;
unsigned int size_;
unsigned int maxsize_;
std::string text_;
Frame* parent_;
public:
Label(Frame* const _parent, std::string &_text, const OrderedPair &_pos,
const unsigned int &_maxsize);
~Label();
inline const Frame* GetParent();
inline unsigned int GetSize();
inline std::string Text();
void SetText(std::string&);
void Move(const OrderedPair &_pos);
void RMove(const OrderedPair &_pos);
void Redraw();
void Clear();
};
如果这太乱了,或者您认为您需要有关我的 classes 的更多信息,请让我在此处添加它们,或者查看我的 GitHub 存储库(public ) 在开发分支 here.
看起来您正在访问矢量范围之外的元素 (_list[loop]
):
for (unsigned int loop = size_; loop < (size_ + _list.size()); loop++) {
list_.push_back(new Label(parent_, _list[loop], {pos_.y + (loop * spacing_), pos_.x}, maxsize_));
for (unsigned int loop = size_; loop < (size_ + _list.size()); loop++)
{
[...] _list[loop] [...]
}
您在列表构造函数中将 size_
设置为 _list.size()
,这意味着您从末尾开始迭代列表,并且 _list[loop]
超出范围。
你不是这个意思吗?
for (unsigned int loop = 0 ; loop < _list.size() ; loop++)
{
[...] _list[loop] [...]
}
C++ 实现的供应商往往花费大量精力来消除标准库实现中的明显缺陷。因此,您的问题的实际原因是一个简单的 std::string
赋值的可能性微乎其微(大约为零)。
几乎可以肯定的是,您程序中的某些代码(在分配发生之前执行)将表现出未定义的行为。这可能包括从数组的末尾脱落(例如访问 x[3]
,其中 x
是一个数组或少于三个元素的 std::vector
),取消引用空指针,使用未初始化的变量.
未定义行为的一个古怪属性是其影响可能不会立竿见影....只是在随后执行的一些完全不相关的代码中发生崩溃。
这几乎肯定会发生在您的代码中。您需要向后工作 - 从崩溃发生的地方 - 找到实际导致问题的实际先前执行的代码语句(或代码语句)。
这是关于 SO 的建议是提供 MCVE 的原因之一 - 删除无关代码的过程可以让您找到真正的原因。如果没有,他们将有机会帮助您……因为您 post 代码实际出现了问题。在这种情况下你没有。
在这种情况下,for
循环是罪魁祸首,因为它访问的容器元素多于它拥有的元素。
我通过很多 classes 跟踪了这个问题,令我惊讶的是,这个错误的根源是一个简单的 std::string = std::string
操作。
我不会post整个代码,只是按顺序执行的函数。我仍然认为 SO 标准的代码太多,但我看不到其他选择。
一些上下文注释:
- OrderedPair 是 public 结构
{ int y, int x }
,位于单独的lib.inc
文件中。 - 前导下划线标记函数头中声明的变量
- 末尾下划线标记一个 class 成员变量
ncefm.cc -- 基本上是主文件
std::vector<std::string> juststring = {"teststring", "another string", "foobar"};
List* list0 = new List(w0_, juststring); // Source of the error
list.cc -- 这里调用了构造函数List()
忽略可选变量,反正不会调用它们
List::List(Frame* const _parent, std::vector<std::string> &_list,
const OrderedPair &_pos = {0, 0}, const unsigned int &_spacing = 1,
const unsigned int &_maxsize = 0) {
pos_ = _pos;
size_ = _list.size();
spacing_ = _spacing;
maxsize_ = _maxsize;
parent_ = _parent;
Fill(_list); //Source of the error
Redraw();
parent_->AddWidget(this);
}
list.cc -- 成员函数Fill()
list_是std::vector
类型的成员变量void List::Fill(std::vector<std::string> &_list) {
for (unsigned int loop = size_; loop < (size_ + _list.size()); loop++) {
list_.push_back(new Label(parent_, _list[loop], {pos_.y + (loop * spacing_),
pos_.x}, maxsize_)); // source of the error (the constructor Label() )
}
}
label.cc -- 这里调用了构造函数 Label()
Label::Label(Frame* const _parent, std::string &_text,
const OrderedPair &_pos = {0,0}, const unsigned int &_maxsize = 0) {
pos_ = _pos;
maxsize_ = _maxsize;
parent_ = _parent;
SetText(_text); // Source of the error
parent_->AddWidget(this);
}
list.cc -- 成员函数SetText()
我们终于到了,错误的来源是...
void Label::SetText(std::string& _text) {
if (maxsize_ != 0 && _text.length() > maxsize_) _text.resize(maxsize_);
text_ = _text; // THIS?!
size_ = text_.length();
Redraw();
}
如果我只是注释掉这一行,错误就会消失, 当然,这会破坏功能。 text_.assign(_text);也不行。
label.h -- 显示头文件和一些变量的定义 text_
class Label {
private:
OrderedPair pos_;
unsigned int size_;
unsigned int maxsize_;
std::string text_;
Frame* parent_;
public:
Label(Frame* const _parent, std::string &_text, const OrderedPair &_pos,
const unsigned int &_maxsize);
~Label();
inline const Frame* GetParent();
inline unsigned int GetSize();
inline std::string Text();
void SetText(std::string&);
void Move(const OrderedPair &_pos);
void RMove(const OrderedPair &_pos);
void Redraw();
void Clear();
};
如果这太乱了,或者您认为您需要有关我的 classes 的更多信息,请让我在此处添加它们,或者查看我的 GitHub 存储库(public ) 在开发分支 here.
看起来您正在访问矢量范围之外的元素 (_list[loop]
):
for (unsigned int loop = size_; loop < (size_ + _list.size()); loop++) {
list_.push_back(new Label(parent_, _list[loop], {pos_.y + (loop * spacing_), pos_.x}, maxsize_));
for (unsigned int loop = size_; loop < (size_ + _list.size()); loop++)
{
[...] _list[loop] [...]
}
您在列表构造函数中将 size_
设置为 _list.size()
,这意味着您从末尾开始迭代列表,并且 _list[loop]
超出范围。
你不是这个意思吗?
for (unsigned int loop = 0 ; loop < _list.size() ; loop++)
{
[...] _list[loop] [...]
}
C++ 实现的供应商往往花费大量精力来消除标准库实现中的明显缺陷。因此,您的问题的实际原因是一个简单的 std::string
赋值的可能性微乎其微(大约为零)。
几乎可以肯定的是,您程序中的某些代码(在分配发生之前执行)将表现出未定义的行为。这可能包括从数组的末尾脱落(例如访问 x[3]
,其中 x
是一个数组或少于三个元素的 std::vector
),取消引用空指针,使用未初始化的变量.
未定义行为的一个古怪属性是其影响可能不会立竿见影....只是在随后执行的一些完全不相关的代码中发生崩溃。
这几乎肯定会发生在您的代码中。您需要向后工作 - 从崩溃发生的地方 - 找到实际导致问题的实际先前执行的代码语句(或代码语句)。
这是关于 SO 的建议是提供 MCVE 的原因之一 - 删除无关代码的过程可以让您找到真正的原因。如果没有,他们将有机会帮助您……因为您 post 代码实际出现了问题。在这种情况下你没有。
在这种情况下,for
循环是罪魁祸首,因为它访问的容器元素多于它拥有的元素。