geostocker
geostocker

Reputation: 1200

Vector not dereferencable

After having looked at the comments I looked through the code and found an error.

It seems after some tinkering I got faced with this error:

Debug error: vector iterator is not dereferencable.

I'm 100% certain that it is in the vector inside assingthreads.

This is the newly added code that spawns the error:

    void historical::writeData(std::vector<std::vector<std::wstring>> in, const string& symbol) {
        std::cout << "Sending data to database connector" << std::endl;
        std::vector<std::vector<std::wstring>> temp;

        while (!in.empty()) {
            for (int i = 0; i < 5; i++) {
                temp.push_back(in.back());
                in.pop_back();
            }
            assignthreads(temp, symbol);
            temp.clear();
        }

    }
    void historical::assignthreads(std::vector<std::vector<std::wstring>> partVec, const string& symbol) {
        int i = 0;
        std::thread threads[5];
        std::vector<std::vector<std::wstring>>::iterator it;
        for (it = partVec.end();
             it != partVec.begin();
             it--) {
            std::shared_ptr<database_con> sh_ptr(new database_con);
            threads[i] = std::thread(&database_con::start, sh_ptr, *it, symbol);
            partVec.pop_back();
            i++;
        }
        for (auto& th : threads) th.join();

    }

Upvotes: 1

Views: 353

Answers (2)

Niall
Niall

Reputation: 30624

At least one issue with the for loop in assignthreads is that you attempt to dereference the end() of the vector;

for (it = partVec.end(); it != partVec.begin(); it--) {
    // ...
    threads[i] = std::thread(&database_con::start, sh_ptr, *it, symbol);
    //                                                    ^^^^
}

And on the first iteration of the loop this is undefined; your debugger is just telling you that.

If you want to "reverse" through the loop, use the reverse_iterator of the container (available via rbegin() and rend())

for (it = partVec.rbegin(); it != partVec.rend(); ++it)

Side note it is generally not advised to modify the container whilst iterating through it (via partVec.pop_back();). Since you don't seem to do anything with what is removed from the vector, it may just as well be better to iterate over the contents, and then call std::vector<>::clear() to remove all the contents from the vector after the loop.

Upvotes: 1

Jonathan Mee
Jonathan Mee

Reputation: 38969

Your first time through the for-loop, it = partVec.end().

By definition you cannot dereference the end of a vector but you call:

threads[i] = std::thread(&database_con::start, sh_ptr, *it, symbol);

The for loop you intended probably used reverse iterators, rbegin and rend like this:

for(auto it = rbegin(partVec); it != rend(partVec); ++it)

A couple additional notes:

  1. Pass your vector by reference: void assignthreads(std::vector<std::vector<std::wstring>>& partVec, const string& symbol)
  2. You need to validate that threads is the same size as partVec. So either do: vector<thread> threads(size(partVec)) or after threads is defined do: assert(size(threads) == size(partVec))

Upvotes: 1

Related Questions