【问题标题】:Heap corruption error occurs when using initializer list使用初始化列表时发生堆损坏错误
【发布时间】:2019-04-08 16:23:40
【问题描述】:

我有一个类,我在堆上创建一个数组。稍后我会增加这个数组的大小。构造类时,我初始化数组。如果我在初始化列表中执行此操作,则在增加数组大小时会出现“堆损坏错误”,但如果我不使用初始化列表,则不会发生这种情况。

请注意,我没有用这两个构造函数创建一个类,但当时只有一个。
为什么在使用初始化器列表时没有按预期工作?

template <typename T>
class Vector {
public:
    Vector() noexcept;

    void push_back(const T& t);

private:
    T* m_arr;
    unsigned int m_size;
    unsigned int m_capacity;

    void realloc();

};

template<typename T>
inline Vector<T>::Vector() noexcept
    : m_size(0), m_capacity(1) {
    m_arr = new T[m_capacity];
    // realloc() works fine with this constructor.
}

template<typename T>
inline Vector<T>::Vector() noexcept
    : m_size(0), m_capacity(1), m_arr(new T[m_capacity]) {
    // Error occurs in realloc() with this constructor.
}

template<typename T>
inline void Vector<T>::push_back(const T& t) {
    if (m_size == m_capacity) {
        m_capacity <<= 1;
        realloc();
    }

    m_arr[m_size] = t;
    ++m_size;
}

template<typename T>
inline void Vector<T>::realloc() {
    T* newArr = new T[m_capacity];
    memcpy(newArr, m_arr, m_size * sizeof(T));
    delete[] m_arr; // Error occurs here with initializer list constructor.
    m_arr = newArr;
}

崩溃代码的示例用法:

int main() {
    Vector vec;
    vec.push_back(0);
    vec.push_back(0); // Crashes here
    vec.push_back(0);

    return 0;
}

【问题讨论】:

  • 我觉得没问题。请发帖minimal reproducible example
  • 好的,我改变了这个例子。我从 Visual Studio 复制粘贴了这个示例,但它确实在我的计算机上崩溃了。
  • 成员按照它们在类中声明的顺序进行初始化,而不是按照您在成员初始化列表中指定的顺序:en.cppreference.com/w/cpp/language/initializer_list
  • 是的,@UnholySheep 是对的。当我更改订单时工作
  • 如果编译器警告被启用,大多数编译器会警告在构造函数的初始化列表中按照它们在类中声明的顺序乱序初始化成员变量。

标签: c++ heap-memory initializer-list


【解决方案1】:

问题

template<typename T>
inline Vector<T>::Vector() noexcept
    : m_size(0), m_capacity(1), m_arr(new T[m_capacity]) {}

在于成员初始化器列表的工作方式 (https://en.cppreference.com/w/cpp/language/initializer_list)。在标题为“初始化顺序”的部分中,它指出:

非静态数据成员按声明顺序初始化 类定义

这意味着由于您的类定义m_arr(new T[m_capacity]) 被执行之前 m_capacity(1) 这意味着new[] 使用未初始化的变量,从而导致未定义的行为

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-06-20
    • 2019-05-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-03-29
    • 1970-01-01
    相关资源
    最近更新 更多