Форум за въпроси

Много интересен бъг в имплементацията на LQueue от лекциите

Много интересен бъг в имплементацията на LQueue от лекциите

by Веселин Иванов -
Number of replies: 3

Когато се опитам да копирам непразна LQueue опашка в друга, чрез конструктура за копиране получавам SEGFAULT. Пуснах дебъгера и забелязах, че в метода copyQueue като бъде извикана push(q.front->inf), в пуша при проверката

if (empty()) {
            front = back = new elem(x);
        } else {
            back->link = new elem(x);
            back = back->link;
        }

дебъгера продължава с реда back->link = new elem(x);, т.е излиза че опашката в която копираме(this)  не е празна от самото начало...WTF? Това възможно ли е?

Но оператора за присвояване изглежда да работи...

In reply to Веселин Иванов

Re: Много интересен бъг в имплементацията на LQueue от лекциите

by Веселин Иванов -

Намерих, къде е бъга! copyQueue e дефинирана по следния начин:

void copyQueue(LQueue const& q) {
        if (q.empty())
            return;
        push(q.front->inf);
        elem *toCopy = q.front->link;
        while (toCopy != NULL) {
            push(toCopy->inf);
            toCopy = toCopy->link;
        }
    }

Kато сложих едно cout << "Empty!!! << endl; в if(empty()) условието на push функцията, което би трябвало да се принтира само когато опашката е празна, забелязах че то се принтира само когато добавям първоначално елементи в опашката, но не и когато опашката се копира с копи конструктора. Т. е излиза, че тогава функцията empty() връща false, т.е член данната front != NULL. Това ме накара да се замисля над това какво се случва, когато се извиква копи конструктора, а именно че както при нормалния конструктор, член данните на класа не са инициализирани, но push функцията, извикана в тялото на copyQueue, очаква те да са правилно инициализирани, все пак пушваме елементи, само когато опашката е вече създадена. НО инициализация на front в copyQueue не се прави и затова стойността и в началото на копирането е неопределена. При мен при всяко пускане на програмата беше false(явно в моята версия на gcc, това е така по подразбиране или просто съм имал рядкото щастие в паметта там да си е имало нула от преди) :)

Фикса за бъга е много прост - добавете ": front(NULL), back(NULL)" като инициализационен списък за копи коструктура.

In reply to Веселин Иванов

Re: Много интересен бъг в имплементацията на LQueue от лекциите

by Веселин Иванов -

Хубаво е същото да се направи и за LStack, понеже той пък се бъгва когато правя копие на празен стек с копи конструктура.

In reply to Веселин Иванов

Re: Много интересен бъг в имплементацията на LQueue от лекциите

by Трифон Трифонов -

Благодаря ти, прав си и за двата проблема.

Наистина, и в двата конструктора за копиране за LQueue и LStack трябва да се сложат инициализиращи списъци, които да нулират указателите: : front(NULL), back(NULL) и stack(NULL), съответно.

Това е прекрасен пример защо не може да се разчита само на тестовете за проверка за коректност: просто проблемът не се вижда когато паметта за въпросните указатели така или иначе съдържа NULL.

Качих поправени версии на шаблоните за свързано представяне съответно на стек и опашка.