【问题标题】:Segmentation fault when implementing my own data type实现我自己的数据类型时出现分段错误
【发布时间】:2021-11-28 14:41:00
【问题描述】:

基本上我正在尝试实现我自己的类似于矢量的数据类型。我这样做只是为了好玩。问题是我在尝试放置 string 类型的新元素时经常遇到 Segmentation fault (试图创建一个名为 person 的结构并且它有一样的问题)。我认为在这种情况下最重要的一段代码(table.h):

template<typename type>
class table
{
    private:
        type* elements = new type[0];
        unsigned int length_ = 0;

        void resize(int change)
        {
            length_ = length_ + change;
            type* elements_ = new type[length_];

            std::memcpy(elements_, elements, length_ * sizeof(type));

            delete[] elements;
            elements = elements_;
        }

    public:
        /* ... */

        void put(type&& element)
        {
            resize(1);
            elements[length_ - 1] = element;
        }
}

然后(ma​​in.cpp):

/* ... */

int main()
{
    table<string> t;
    t.append("Hello World"); // segfault
    for(string s : t) {cout << s << endl;}

    /* But this works:
    table<char*> t;
    t.append((char*)"Hello World");
    for(string s : t) {cout << s << endl;} */
}

【问题讨论】:

  • 提供的代码不会重现所描述的问题。并且 std::memcpy 正在用于非 memcpy-able 对象。
  • 不要使用new:使用std::vector。我从未见过在初始化语句中使用new。它可能有效,也可能无效。
  • 您不能在string 等一般类型上使用memcpy。大致而言,string 包含一个指向实际字符串数据所在的 char 的指针。如果我们memcpy,我们会得到两个具有相同指针的字符串,然后当两者都被破坏时,我们会对同一个指针执行双重释放,这是未定义的行为。 memcpy 只对非常基本的数据类型是安全的。
  • 查看相关question

标签: c++ segmentation-fault


【解决方案1】:

在这段代码中

length_ = length_ + change;
type* elements_ = new type[length_];

std::memcpy(elements_, elements, length_ * sizeof(type));

您正在递增length_,然后将elements 数组中的许多元素复制到新数组中。但是elements 里面只有length_ - change 元素。所以它试图从数组边界之外复制数据,这是未定义的行为。

正如 cmets 中提到的,您不能将 std::memcpy 用于 std::string 之类的类型。它只能用于trivially copyable 类型。你可以这样做:

unsigned int newLength = length_ + change;
type* elements_ = new type[newLength];
std::copy(elements, elements + length_, elements_);
length_ = newLength;

或者更好,但只需使用std::vector&lt;type&gt;

template<typename type>
class table
{
    private:
        std::vector<type> elements;

    public:
        /* ... */

        void put(type&& element)
        {
            elements.emplace_back(std::move(element));
        }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-09-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-03
    • 2020-06-01
    • 1970-01-01
    相关资源
    最近更新 更多