Valgrind говорит, что const-iterator пытается получить доступ к неинициализированному пространству, но на самом деле это - PullRequest
0 голосов
/ 09 февраля 2012

Я пытаюсь использовать 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;
}

Но что-то не так, как сообщает Вальгринд.

== 4662 == Использование неинициализированного значения размера 8

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

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

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

== 4662 == по 0x401D63: main (main.cpp: 121)

== 4662 ==

== 4662 == Недопустимое чтение размера 4

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

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

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

== 4662 == по 0x401D63: main (main.cpp: 121)

== 4662 == Адрес 0xa680020611a25ff не является стековым, malloc или (недавно) свободным

== 4662 ==

== 4662 ==

== 4662 == Процесс завершается с действием по умолчанию для сигнала 11 (SIGSEGV)

== 4662 == Ошибка общей защиты

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

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

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

== 4662 == по 0x401D63: main (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 для других целей, и они работают. Я думаю, что это что-то, связанное с константностью, но не могу понять, что.

Ответы [ 2 ]

2 голосов
/ 09 февраля 2012

"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 - это указатель, который указывает на динамически распределяемые данные (element).Мы также видим, что ваш конструктор копирования делает поверхностную копию этого указателя, а это означает, что как только вы создаете его из пыльника, временный объект удаляется, и «новый» итератор указывает на недопустимую память.И это будет иногда "работать".За исключением иногда это не так.Или это может установить вирус.Или что угодно.Не стоит недооценивать Неопределенное поведение

a=matd.cbegin();
(1) cbegin() создает итератор, который выделяет новый element.
(2), который вы назначаетевременно к a, и скопируйте указатель.
(3) Временное удаляется и удаляет element.
(4) a, теперь указывающее на этот (недопустимый) удаленный элемент

Обычный совет на этом этапе - всегда назначать выделенную память для умного указателя, почти всегда std::unique_ptr, и у вас больше не будет этой проблемы.Совет: если в вашем коде delete, вы делаете это неправильно.

1 голос
/ 09 февраля 2012

Это решило мою проблему: Использование неинициализированного значения размера 8

Ошибка в коде.В операторе присваивания итератора я забыл инициализировать фундаментальное значение.Это привело к тому, что все итераторы, за исключением begin (), прочитали не в том месте, поскольку их указатель на sparsematrix не был инициализирован.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...