2

I've been having this problem while trying to create a generic Priority Queue.

Valgrind gives me these errors :

  HEAP SUMMARY:
==39639==     in use at exit: 0 bytes in 0 blocks
==39639==   total heap usage: 22 allocs, 22 frees, 1,811 bytes allocated
==39639== 
==39639== All heap blocks were freed -- no leaks are possible
==39639== 
==39639== ERROR SUMMARY: 4 errors from 2 contexts (suppressed: 6 from 6)
==39639== 
==39639== 2 errors in context 1 of 2:
==39639== Invalid read of size 8
==39639==    at 0x405FB5: mtm::PriorityQueue<int, Assignment>::Iterator::operator++() (priority_queue.h:505)
==39639==    by 0x405D2E: mtm::PriorityQueue<int, Assignment>::erase(mtm::PriorityQueue<int, Assignment>::Iterator, mtm::PriorityQueue<int, Assignment>::Iterator) (priority_queue.h:808)
==39639==    by 0x403BC0: eraseAndSizeTest() (priority_queue_test.cpp:119)
==39639==    by 0x404D6B: main (priority_queue_test.cpp:136)
==39639==  Address 0x5141c88 is 24 bytes inside a block of size 32 free'd
==39639==    at 0x4A05FD6: operator delete(void*) (vg_replace_malloc.c:480)
==39639==    by 0x405B1B: mtm::PriorityQueue<int, Assignment>::erase(mtm::PriorityQueue<int, Assignment>::Iterator) (priority_queue.h:768)
==39639==    by 0x405D04: mtm::PriorityQueue<int, Assignment>::erase(mtm::PriorityQueue<int, Assignment>::Iterator, mtm::PriorityQueue<int, Assignment>::Iterator) (priority_queue.h:809)
==39639==    by 0x403BC0: eraseAndSizeTest() (priority_queue_test.cpp:119)
==39639==    by 0x404D6B: main (priority_queue_test.cpp:136)
==39639== 
==39639== 
==39639== 2 errors in context 2 of 2:
==39639== Invalid read of size 8
==39639==    at 0x4CCB870: std::string::size() const (basic_string.h:713)
==39639==    by 0x4050E8: __gnu_cxx::__enable_if<std::__is_char<char>::__value, bool>::__type std::operator==<char>(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) (in /u1/115/saoren/mtm/HW5/wet5/prog)
==39639==    by 0x405048: Assignment::operator==(Assignment const&) const (priority_queue_test.cpp:26)
==39639==    by 0x406337: mtm::PriorityQueue<int, Assignment>::Iterator::operator==(mtm::PriorityQueue<int, Assignment>::Iterator const&) const (priority_queue.h:553)
==39639==    by 0x406010: mtm::PriorityQueue<int, Assignment>::Iterator::operator=(mtm::PriorityQueue<int, Assignment>::Iterator const&) (priority_queue.h:451)
==39639==    by 0x405D1B: mtm::PriorityQueue<int, Assignment>::erase(mtm::PriorityQueue<int, Assignment>::Iterator, mtm::PriorityQueue<int, Assignment>::Iterator) (priority_queue.h:809)
==39639==    by 0x403BC0: eraseAndSizeTest() (priority_queue_test.cpp:119)
==39639==    by 0x404D6B: main (priority_queue_test.cpp:136)
==39639==  Address 0x5141c70 is 0 bytes inside a block of size 32 free'd
==39639==    at 0x4A05FD6: operator delete(void*) (vg_replace_malloc.c:480)
==39639==    by 0x405B1B: mtm::PriorityQueue<int, Assignment>::erase(mtm::PriorityQueue<int, Assignment>::Iterator) (priority_queue.h:768)
==39639==    by 0x405D04: mtm::PriorityQueue<int, Assignment>::erase(mtm::PriorityQueue<int, Assignment>::Iterator, mtm::PriorityQueue<int, Assignment>::Iterator) (priority_queue.h:809)
==39639==    by 0x403BC0: eraseAndSizeTest() (priority_queue_test.cpp:119)
==39639==    by 0x404D6B: main (priority_queue_test.cpp:136)
==39639== 
--39639-- 
--39639-- used_suppression:      4 U1004-ARM-_dl_relocate_object
--39639-- used_suppression:      2 glibc-2.5.x-on-SUSE-10.2-(PPC)-2a
==39639== 
==39639== ERROR SUMMARY: 4 errors from 2 contexts (suppressed: 6 from 6)

and here is my code (relevent parts, I believe) :

template<typename Priority, typename T>
typename PriorityQueue<Priority, T>::Iterator PriorityQueue<Priority, T>::Iterator::operator+(
        int offset) {

    if (offset == 0) {
        return *this;
    }

    Iterator it = *this;

    for (int i = 0; i < offset; i++) {
        it++;
    }

    //TODO: SHOULD WE ALLOCATE NEWITERATOR WITH NEW ??

    return it;
}`

`template<typename Priority, typename T>
typename PriorityQueue<Priority, T>::Iterator PriorityQueue<Priority, T>::Iterator::operator++() {
    //TODO: CHECK IF NOT NULL

    if (this->data != nullptr) {

        data = data->next;
        index++;
    }

    return *this;
}

    template<typename Priority, typename T>
    typename PriorityQueue<Priority, T>::Iterator PriorityQueue<Priority, T>::Iterator::operator++(
            int) {

        Iterator it = *this;

        if (this->data != nullptr) {

            if (this->data->next == nullptr) {
                data = nullptr;
                index++;
                return *this;
            }

            data = data->next;
            index++;
        }

        return it;
    }

template<typename Priority, typename T>
typename PriorityQueue<Priority, T>::Iterator PriorityQueue<Priority, T>::erase(
        Iterator exactPosition) {

    if (elementsNo == 0) {
        return end();
    }

    bool lastOne = false;
    bool firstOne = false;
    lastOne = exactPosition + 1 == end();
    firstOne = exactPosition == begin();
    if (firstOne) {
        elementsNo--;
        head = head->next;
        delete (exactPosition.data);
        exactPosition.data = nullptr;
        return begin();
    }

    Iterator previousPosition = begin();

    while (previousPosition.data->next != exactPosition.data) {
        previousPosition++;
    }

    if (lastOne) {
        elementsNo--;
        delete exactPosition.data;
        previousPosition.data->next = nullptr;
        return end();
    }

    Node* next = exactPosition.data->next;
    previousPosition.data->next = next;

    delete exactPosition.data;
    exactPosition.data = nullptr;
    this->elementsNo--;

    return Iterator(next, exactPosition.index + 1);

}

template<typename Priority, typename T>
typename PriorityQueue<Priority, T>::Iterator PriorityQueue<Priority, T>::erase(
        Iterator start, Iterator end) {

    if (!size()) {
        return end;
    }
    //TODO: CHECK BOUNDRIES (START AFTER END)
    Iterator iterator = start;

    //FOREACH(iterator,start,end)
    for (Iterator i = start; i != end; ++i) {
        iterator = erase(iterator);
    }

    return ++iterator;


template<typename Priority, typename T>
bool PriorityQueue<Priority, T>::Iterator::operator==(
        const Iterator& original) const {

    if (data == nullptr && original.data == nullptr) {
        return true;
    }
    if (data == nullptr || original.data == nullptr) {
        return false;
    }

    return data->element.data == original.data->element.data;
}

I would really appreciate it if someone could spot the faults and let me know even though there a lot of functions and a lot of errors it's all goes down to erase.

ROMANIA_engineer
  • 54,432
  • 29
  • 203
  • 199

1 Answers1

1

In the erase( Iterator start, Iterator end) function you do the following at the end of the function:

    return ++iterator;

If the end iterator passed into the function is in fact the container's end iterator then you're returning an iterator that's past the end of the container.

Since erase( Iterator exactPosition) returns the iterator following the one erased, you should simply return iterator from erase( Iterator start, Iterator end).

Michael Burr
  • 333,147
  • 50
  • 533
  • 760
  • 1
    I have to laugh... all I saw was Iterator... Iterator... Iterator... Iterator... Iterator... Iterator... Iterator... It's `Iterators` all the way down! – lornix Jun 21 '14 at 21:17