C++ Valgrind说const迭代器试图访问未初始化的空间,但实际上是这样
我试图使用常量迭代器遍历元素列表(矩阵的元素) 常量迭代器的复制构造函数:C++ Valgrind说const迭代器试图访问未初始化的空间,但实际上是这样,c++,iterator,constants,initialization,const-iterator,C++,Iterator,Constants,Initialization,Const Iterator,我试图使用常量迭代器遍历元素列表(矩阵的元素) 常量迭代器的复制构造函数: const_iterator(const const_iterator& it) { e=it.e; } 此外,在类的方法中创建和使用的常量迭代器工作得非常好 附言: 芬德罗密码 mrow* findRow(int i) const { mrow *tmp = matrix; while(tmp!=NULL){ if(tmp->idx == i) return tm
const_iterator(const const_iterator& it) { e=it.e; }
此外,在类的方法中创建和使用的常量迭代器工作得非常好
附言:
芬德罗密码
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)的代码
如果您需要更多的代码,请询问
此外,让我再次确认,我将findRow和findNext用于其他目的,并且它们是有效的。我认为这与常量有关,但无法得到什么。“在0x403A19处使用大小为8的未初始化值:SparseMatrix::findRow(int)const(SparseMatrix.h:120)”
和“在0x403A27处读取大小为4的无效值: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
所以,这告诉我你的对象是无效的。如果您确定常量迭代器与此有关,那么我认为常量迭代器的内部SparseMatrix*
指针不正确。我们可以看到复制构造函数和/或操作符++()
[编辑]现在我已经看到operator++
删除它的e
成员,并将其分配给findNext
的结果,我们知道e
是指向动态分配数据的指针(一个元素
)。我们还看到,您的复制构造函数对该指针进行了浅层复制,这意味着一旦您从另一个指针创建了一个指针,该临时指针将被删除,“新”迭代器将指向无效内存。它有时会“起作用”。但有时不会。或者它可能安装病毒。或者别的什么。不要低估
a=matd.cbegin()代码>
(1) cbegin()
(2) 将该临时值分配给a
,然后复制指针。
(3) 将删除临时文件,并删除元素
(4) a
现在指向该(无效)已删除元素
此时通常的建议是,总是将分配的内存分配给一个智能指针,几乎总是一个std::unique\u ptr
,这样您就不会再有这个问题了。提示:如果您的代码中有删除
,则说明您做错了。这解决了我的问题:
这是代码中的一个错误。在迭代器赋值运算符中,我忘记初始化基本值。这导致除begin()之外的所有迭代器读取错误的位置,因为它们指向sparsematrix的指针没有初始化 如果对函数operator++
和find…
没有任何概念,就很难回答,仅仅因为tmp
不是空的,并不意味着它是有效的-可能是在您的ctor中,您不使用任何东西初始化它…您使用的是什么SparseMatrix
?它不是标准的。我将它实现为列表列表,作为练习。@Vektor88因为错误在SparseMatrix
类中,这是我们必须看到的代码,以便能够提供帮助。@Vektor88:您的SparseMatrix是否遵循标准?具体来说,就是复制构造函数和赋值运算符。如果不是,错误可能在findRow
中,但正如我第三次说的,如果我使用普通迭代器,它不会给出任何错误,因此它必须是常量迭代器。无论如何,我也要加上它。@Vektor88:valgrind清楚地表明,这些都是您的问题的直接原因。如果我们向后看,我们可能会发现一系列事件是由常量迭代器触发的,但这是第一步。@Vektor88:我实现了另一种可能的连接,我们可以看到常量迭代器的复制构造函数和/或操作符++()?操作符++已经发布,现在我将添加复制构造函数。他们就在瓦尔格兰报告的下面。@Vektor88好吧,不管怎样,那都是你问题的一部分。您要么有双重删除,要么内存泄漏。解决办法是一样的。您应该能够用std::unique\u ptr
替换所有元素*
,任何不编译的东西都可能是错误的。
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 r, int c, T d){
rows=r;
cols=c;
def=d;
msize=0;
matrix=NULL;
}
mrow *tmp = matrix; //matrix is unassigned, but not NULL. It's random
tmp=tmp->next; //then dereferenced a completely random place in memory