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

memory corrupted using std::vector in constructor

本文关键字:vector 内存 损坏 std 构造函数      更新时间:2023-10-16

给定一个字符串数组,我正在编写一个类,根据它们的长度将它们分为不同的组,即相同长度的字符串属于同一组。组的数量和每个组的大小都是未知的。

我的想法如下:我使用私有数据成员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(){for(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的使用有关。用户表单提供了一条有趣的线索:外部std::vector在其堆分配中存储了一个固定大小的std::vector<int>数据结构数组

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

我很感激你抽出时间。

下面的一些改进。特别是,您有一个偏离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中越界,因为唯一有效的条目是m_cst2[0]

因此,内存损坏可能与std::vector无关(很难弄乱对象的向量),它很可能与上面的代码有关。

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