简单的字符串分配导致分割故障

Simple string assignment causing a segmentation fault?

本文关键字:分割 故障 分配 字符串 简单      更新时间:2023-10-16

我已经通过我的课程跟踪了这个问题,令我惊讶的是,此错误的来源是一个简单的std::string = std::string操作。

我不会发布整个代码,只是按顺序执行的函数。我仍然认为SO标准的代码太多了,但是我没有其他选择。

一些上下文注释:

  • OrderedPair是单独的lib.inc文件中的公共结构{ int y, int x }
  • 领导下划线标记在功能标题中声明的变量
  • 尾随下划线标记了类成员变量

ncefm.cc-基本上是主文件

std::vector<std::string> juststring = {"teststring", "another string", "foobar"};
List* list0 = new List(w0_, juststring); // Source of the error

list.cc- constructor 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-成员函数填充()

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- constructor 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_.sign(_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();
};

如果这太混乱了,或者您认为您需要有关我的课程的更多信息,请我在这里添加它们,或在此处查看我的github repo(public)。

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] [...]
}

看起来您正在访问向量范围之外的元素(_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_));

C 实现的供应商倾向于采用大量精力来消除其标准库的实施中明显的缺陷。因此,您问题的实际原因的几率是简单的std::string分配的分配很小(大约为零)。

几乎可以肯定会发生的是,您程序中的某些代码(在分配发生之前执行)将表现出不确定的行为。这可能包括从数组的末端掉下来(例如,访问x[3],其中x是数组或少于三个元素的std::vector),使用非初始化的变量来删除NULL指针。

未定义行为的Quainter属性之一是效果可能不是立即的。...仅在某些完全无关的代码中发生崩溃。

这几乎可以肯定在您的代码中发生。您需要向后工作 - 从崩溃发生的地步 - 才能找到实际引起问题的实际执行代码语句(或代码语句)。

这是提供建议的原因之一,就是提供MCVE-切除无关的代码的过程可以使您找到实际原因。如果不是这样,他们有人有帮助您的战斗机会...因为您张贴了实际上表现出问题的代码。在这种情况下您还没有。

在这种情况下, for循环是罪魁祸首,因为它访问了容器的元素超过其。