-2

我正在尝试使用 const_iterators 来遍历元素列表(矩阵的元素)。

SparseMatrix matd(5,5,0); //5x5 matrix with 0 as default element.
//Follows elements insertion...
SparseMatrix<int>::const_iterator a,b;
a=matd.cbegin();
b=matd.cend();
while(a!=b){
    cout<<*(a->data)<<endl;
    ++a;
}

但正如 valgrind 报告的那样,有些地方出了问题。

==4662== 使用大小为 8 的未初始化值

==4662== 在 0x403A19: SparseMatrix::findRow(int) const (SparseMatrix.h:120)

==4662== by 0x40431A: SparseMatrix::findNext(el const*) const (SparseMatrix.h:439)

==4662== by 0x4030B3: SparseMatrix::const_iterator::operator++() (SparseMatrix.h:593)

==4662== 由 0x401D63: 主要 (main.cpp:121)

==4662==

==4662== 大小为 4 的读取无效

==4662== 在 0x403A27: SparseMatrix::findRow(int) const (SparseMatrix.h:123)

==4662== by 0x40431A: SparseMatrix::findNext(el const*) const (SparseMatrix.h:439)

==4662== by 0x4030B3: SparseMatrix::const_iterator::operator++() (SparseMatrix.h:593)

==4662== 由 0x401D63: 主要 (main.cpp:121)

==4662== 地址 0xa680020611a25ff 没有被堆栈、malloc 或(最近)释放

==4662==

==4662==

==4662== 进程以信号 11 (SIGSEGV) 的默认操作终止

==4662== 一般保护故障

==4662== 在 0x403A27: SparseMatrix::findRow(int) const (SparseMatrix.h:123)

==4662== by 0x40431A: SparseMatrix::findNext(el const*) const (SparseMatrix.h:439)

==4662== by 0x4030B3: SparseMatrix::const_iterator::operator++() (SparseMatrix.h:593)

==4662== 由 0x401D63: 主要 (main.cpp:121)

因为我将 findNext 和 findRow 与普通迭代器和其他类方法一起使用,并且它们可以工作,所以我认为 operator++() 有问题:

const_iterator& operator++() { const element *tmp=e; e=sm->findNext(tmp); delete tmp; return *this; }

const_iterator 的复制构造函数:

const_iterator(const const_iterator& it) { e=it.e; }

此外,在类的方法中创建和使用的 const_iterator 工作得很好。

PS:findRow的代码

    mrow* findRow(int i) const {
    mrow *tmp = matrix;
    while(tmp!=NULL){
        if(tmp->idx == i) return tmp;
        tmp=tmp->next;
    }   
    return NULL;
}

它通过了一个 if(tmp==NULL) 检查,所以它认为内存中有一些东西,但是它说它没有初始化,但我再说一遍,如果我使用正常的迭代器它可以工作。

这是 findNext 的代码

    element* findNext(const element* e) const {
    int r=e->i; 
    int c=e->j;
    int riga,colonna; 
    riga=r;
    while(riga!=-1){
            if(riga==r) {
                mrow *m=findRow(riga); 
                colonna=nextCol(m,c);
                if(colonna!=-1) {
                    T* d=&((findCol(findRow(riga),colonna)->data)); 
                    return genElement(riga,colonna,d);      
                }           
            }
            else{
                colonna=nextCol(findRow(riga),-1);
                if(colonna!=-1) {
                    T* d=&((findCol(findRow(riga),colonna)->data));
                    return genElement(riga,colonna,d);      
                }                       
            }
            riga=nextRow(riga);
    }
    return NULL;
}

构造函数 SparseMatrix(int,int,T) 的代码

    SparseMatrix(int r, int c, T d){
    rows=r;
    cols=c;
    def=d;
    msize=0;
    matrix=NULL;
}

如果您需要更多代码,请询问。

此外,让我再次确认我将 findRow 和 findNext 用于其他目的,并且它们可以工作。我认为这与 constness 有关,但无法得到什么。

4

2 回答 2

2

"Use of uninitialised value of size 8 at 0x403A19: SparseMatrix::findRow(int) const (SparseMatrix.h:120)""Invalid read of size 4 at 0x403A27: SparseMatrix::findRow(int) const (SparseMatrix.h:123)"

告诉我们您从一个未初始化的值中读取,然后在三行之后,您取消引用了一个无效指针。从您显示的代码中,那些必须与这些行相对应:

mrow *tmp = matrix; //matrix is unassigned, but not NULL.  It's random
tmp=tmp->next; //then dereferenced a completely random place in memory

所以,这告诉我你的对象是无效的。如果您确定 const 迭代器与它有关,我想 const_iterator 的内部SparseMatrix*指针是不正确的。我们可以看到复制构造函数和/或operator++()?

[编辑] 现在我已经看到operator++删除它的e成员,并将其分配给 的结果findNext,我们知道这e是一个指向动态分配数据的指针(an element)。我们还看到您的复制构造函数对该指针进行了浅拷贝,这意味着一旦您从 anther 创建一个,临时的就会被删除,并且“新”迭代器指向无效内存。它有时会“工作”。除了有时不会。或者它可能会安装病毒。管他呢。不要低估未定义的行为

a=matd.cbegin();
(1)cbegin()创建一个迭代器,它分配一个新的element.
(2)您将该临时分配给a,并复制指针。
(3) 临时删除,删除element.
(4)a现在指向那个(无效的)已删除元素

此时的正常建议是始终将分配的内存分配给智能指针,几乎总是 a std::unique_ptr,您将不会再遇到此问题。提示:如果你delete的代码中有,那么你做错了。

于 2012-02-08T23:35:49.420 回答
1

这解决了我的问题: Use of uninitialized value of size 8

这是代码中的错误。在迭代器赋值运算符中,我忘记初始化一个基本值。这导致除了 begin() 之外的所有迭代器都读取到错误的位置,因为它们指向 sparsematrix 的指针未初始化。

于 2012-02-09T18:53:28.800 回答