在构造函数中使用 std::vector 内存损坏

memory corrupted using std::vector in constructor

给定一个字符串数组,我正在写一个 class 来根据它们的长度将它们分成不同的组,即相同长度的进入同一组。组数和每个组的大小未知。

我的思路如下: 我使用私有数据成员 std::vector<std::vector<std::int> > m_groups,目的是让外部向量维护组,而内部向量跟踪属于一个组的所有字符串索引。

问题是,一旦我将字符串放入向量中,我的一些数据成员就会损坏。有人可以看看吗?

这里是简化代码:

class A {

public:
    A(std::string words[], int num, int c1[], int m, int c2[], int n);
    ~A();

    void print_state();

private:

    int *m_var; 
    int m_Nvar;

    std::vector<std::vector<std::int> > m_doms;
    std::vector<std::vector<std::int> > m_groups;
    std::vector<std::string> > m_words;

    int *m_cst1;
    int *m_cst2;
    int m_Ncst;
};

在构造函数中: A::print_cst2() { 对于 (int c = 0; c < m_Ncst; c++) { printf("%d", m_cst2[4*c]); printf("%d", m_cst2[4*c+1]); printf("%d", m_cst2[4*c+2]); printf("%d", m_cst2[4*c+3]); } }

A::A(std::string words[], int num,
    int c1[], int m, int c2[], int n) {

    ...
    m_cst1 = new int[m/2];
    m_cst2 = new int[n/4];
    m_Ncst = n/4;
    m_Nvar = m/2;

    for (int i = 0; i < n; i+=4)
    {
        m_cst2[i] = c2[i];
        m_cst2[i+1] = c2[i+1];
        m_cst2[i+2] = c2[i+2];
        m_cst2[i+3] = c2[i+3];
    }

    print_cst2();  // (1) we print the m_cst2 
    // we are only interested, the words of length smaller than m_max_len
    // put m_max_len number of empty vectors (groups) in the group vector
    for (int i = 0; i < m_max_len; i++)
    {   
        m_groups.push_back(std::vector<int>());
    }   
    print_cst2();  // (2) we print the m_cst2 again 

    // go through every words and copy words of interest to m_words
    // push the index of the word to the group it belongs to (by its length)
    for (int i = 0, k = 0; i < num; i++, k++)
    {   
        int len = words[i].length();
        if (len > m_max_len)
            continue;
        m_words.push_back(words[i]);
        m_groups[len].push_back(k);
    }

    // you can ignore this part: link the group to another structure
    for (int i = 0; i < m_Nvar; i++)
    {
         m_doms.push_back(m_groups[m_cst1[i]]);
    }

    ...
}

...

我编译了代码运行。数组 m_cst2 末尾的数据已损坏。这似乎与 std::vector 的使用有关。 User comingstorm provided an interesting clue外部 std::vector 在其堆分配中存储了一个固定大小的数组 std::vector<int> 数据结构。 这就是答案吗?虽然不确定。所以,post 在此求教。

PS:如果你有更好的想法来完成这个任务,请告诉我......如果你需要更多信息,请post。

感谢您抽出时间。

下面的一些改进。特别是你有一个 off by 1 索引错误并且 k 的增量不正确:

CwordSolver::CwordSolver(std::string words[], int num,
int c1[], int m, int c2[], int n) {

    ...

    // we are only interested, the words of length smaller than m_max_len
    m_groups.resize(0);
    m_groups.resize(m_max_len, std::vector<int>());

    // go through every words and copy words of interest to m_words
    // push the index of the word to the group it belongs to (by its length)
    int k = 0;    // the index in m_words
    for (int i = 0; i < num; i++)
    {   
        int len = words[i].length();
        if (len >= m_max_len)
            continue;
        m_words.push_back(words[i]);
        m_groups[len].push_back(k);
        k++;
    }

    ...
}

如果您发布的代码是您正在使用的实际代码,那么这会破坏内存。

假设 n 是 4。

m_cst2 = new int[n/4];  // so you have room for 1 item
m_Ncst = n/4;
m_Nvar = m/2;

for (int i = 0; i < n; i+=4)
{
    m_cst2[i] = c2[i];      // valid
    m_cst2[i+1] = c2[i+1];  // memory overwrite
    m_cst2[i+2] = c2[i+2];  // memory overwrite
    m_cst2[i+3] = c2[i+3];  // memory overwrite
}

没有必要更进一步。 n 的值为 4,很明显,当您写入 m_cst2[1], m_cst2[2] 时,您将在 m_cst2 中越界,因为唯一有效的条目是 [=15] =].

所以你的内存损坏可能与 std::vector 无关(很难弄乱对象向量),而且很可能与上面的代码有关。

此外,您应该在代码中使用 std::vector 而不是 new[]/delete[]。如果您打算将 vector 用于一件事,为什么不随时随地利用它呢?