-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== at 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== by 0x401D63: メイン (main.cpp:121)

==4662==

==4662== サイズ 4 の無効な読み取り

==4662== at 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== by 0x401D63: メイン (main.cpp:121)

==4662== アドレス 0xa680020611a25ff は、スタック、malloc、または (最近) 解放されていません

==4662==

==4662==

==4662== シグナル 11 (SIGSEGV) のデフォルト アクションで終了するプロセス

==4662== 一般保護違反

==4662== at 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== by 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_iterators は非常にうまく機能します。

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)"

初期化されていない値から読み取り、3 行後に無効なポインターを逆参照したことがわかります。あなたが示したコードから、それらは次の行に対応している必要があります:

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ことがわかります。また、コピー コンストラクターがそのポインターの浅いコピーを実行していることもわかります。つまり、別のポインターを作成するとすぐに、一時的なものは削除され、「新しい」イテレーターは無効なメモリを指しています。そして、それは時々「うまくいく」でしょう。時々そうでないことを除いて。または、ウイルスをインストールする可能性があります。または何でも。未定義の動作を過小評価しないでくださいeelement

a=matd.cbegin();
(1)cbegin()新しい を割り当てるイテレータを作成しますelement
(2) に一時的に割り当てa、ポインタをコピーします。
(3) テンポラリを削除し、 を削除しelementます。
(4)aその (無効な) 削除された要素を指すようになりました

この時点での通常のアドバイスは、常に割り当てられたメモリをスマート ポインター (ほとんどの場合) に割り当てることでstd::unique_ptrあり、この問題が再び発生することはありません。ヒント:deleteコードに がある場合は、間違っています。

于 2012-02-08T23:35:49.420 に答える
1

これで私の問題は解決しました: サイズ8の初期化されていない値の使用

コードのエラーでした。イテレータ代入演算子で、基本値を初期化するのを忘れました。これにより、begin()を除くすべてのイテレータが、スパース行列へのポインタが初期化されなかったため、間違った場所で読み取られました。

于 2012-02-09T18:53:28.800 に答える