Need a bit of help from you.
I am writing an application for c++ having the use of queue STL container in my code.
While accessing the front() element of that queue, I am encountering a "deque iterator not dereferencable" error. This specific error is coming in debug mode only.
The code is below.
// haraldMsgDb is a queue of strings declared in header file
// std::queue <std::string> haraldMsgDb;
void handle_message(Message& message)
{
std::string dataString = "\"" + std::string(message.getName()) + "\":" + std::string("#") + "\"" + std::string(message.getTime().toString()) + "\"" + std::string(":") + "\"" + std::string(message.getData()) + "\"";
/* pushing data in queue here*/
App::Instance->haraldMsgDb.push(dataString);
}
/*fetching the queue data in this function*/
void SendData()
{
/*Some stuff*/
while (1)
{
while (!TimeSeriesApp::TimeSeriesAppInstance->haraldMsgDb.empty())
{
if (data.length() < 3000)
{
data += App::Instance->haraldMsgDb.front(); // ---->>> getting the "deque iterator not dereferencable" error here, somtimes the error comes in below line as well
std::string key = App::Instance->haraldMsgDb.front().substr(0, App::Instance->haraldMsgDb.front().find("#"));
std::string value = App::Instance->haraldMsgDb.front().substr(App::Instance->haraldMsgDb.front().find("#") + 1, std::string::npos);
App::Instance->haraldMsgDb.pop();
if (jsonMap.find(key) != jsonMap.end())
jsonMap[key] = jsonMap[key] + "," + value;
else
jsonMap.insert(std::make_pair(key, value));
}
else
{
if (ret == MOSQ_ERR_SUCCESS)
{
str = "{";
for (auto itr = jsonMap.begin(); itr != jsonMap.end(); ++itr) {
str += itr->first + "\n" + "\t\t{" + itr->second + "},\n";
}
str = str.substr(0, str.length() - 2);
str += "}";
}
LOGMESSAGE("data..." << str << std::endl);
LOGMESSAGE("length " << str.length() << std::endl);
/*Some stuff*/
}
}
}
}
int main()
{
handle_incoming_message();
sendData();
return 0;
}
The error is coming in line below while accessing the front element:
data += App::Instance->haraldMsgDb.front();
As I am popping the data from the queue, hence I am checking if the queue is not empty before accessing the front() of queue. but still getting the error.
When I am debugging thoroughly, the error is coming in deque file of Visual Studio:
reference operator*() const
{ // return designated object
const auto _Mycont = static_cast<const _Mydeque *>(this->_Getcont());
#if _ITERATOR_DEBUG_LEVEL == 2
if (_Mycont == 0
|| this->_Myoff < _Mycont->_Myoff
|| _Mycont->_Myoff + _Mycont->_Mysize <= this->_Myoff)
{ // report error
_DEBUG_ERROR("deque iterator not dereferencable");
}
Here, _Mycont is getting null/zero, which is upfront throwing this exception. Could anyone let me know why I am getting this error?
Related
I have created a template class that implement a circular buffer. The buffer is formed of items that have a value of type T.
I want to define the operator[ ] to write and read an element of the buffer. Even when I try to read an element already inizialized the result is: Segmentation fault: 11
This is the code for operator[ ]:
// read
const T& operator[](size_type index) const {
assert(index < _size);
item *curr = _buffer + index;
return curr->value;
}
// read and write
T &operator[](size_type index) {
assert(index < _capacity);
item *curr = _buffer + index;
if (index < _size) {
return curr->value;
}
else {
_size++;
return curr->value;
}
}
An example of how I use operator[ ] in main.cpp:
cbuffer<int> b(4);
std::cout << "b: " << b << std::endl;
std::cout << "capacity: " << b.capacity() << std::endl;
assert(b.capacity() == 4);
std::cout << "size: " << b.size() <<
std::endl;
assert(b.size() == 0);
b[0] = 1;
b[1] = 3;
The error occurs when I try to write a new item in the buffer.
What could be a way to define the operator[ ] that works?
I'm guessing somewhat, because you haven't provided enough context (it's difficult to see if a small part of a class is correct without seeing the rest of the class). But it seems that _buffer is a linked list. The next pointer in the item struct gives it away
typedef struct item {
T value;
item *next;
};
But your operator[] code assumes that _buffer is an array,
item *curr = _buffer + index;
Using + on a pointer assumes that the pointer is pointing at a contiguous block of memory but because you have a linked list that's not the case for you.
Instead you need to write a loop, that loops through your linked list until you find the correct item. Something like this
item *curr = _buffer;
while (index > 0) {
curr = curr->next;
--index;
}
return curr->value;
This question already has answers here:
How to remove from a map while iterating it?
(6 answers)
Closed 5 years ago.
I am trying to determine the maximum number of items I can remove from a list using std list to get the minimum size. However, it keeps ending up in bad memory access.
This is my recursive function:
int step (list<int> mylist) {
int count = mylist.size();
// Terminations
if (!checkRemaining(mylist)) {
return mylist.size();
}
if (mylist.empty()) {
return 0;
}
//printf("mysize: %d\n", mylist.size());
// Else we do not terminate first
for (auto i=mylist.begin(); i != prev(mylist.end()); ++i)
{
if ((*i + *next(i))%2 == 0) // Problem starts from here, bad access
{
mylist.erase(next(i));
mylist.erase(i);
printf("this size %lu\n", mylist.size());
list<int> tempList = mylist;
for (auto it = tempList.begin(); it != tempList.end(); it++) {
printf("%d ", *it);
}
printf("\n");
int temp = step (tempList);
if (temp < count) count = temp;
}
}
return count;
}
It managed to get down to the desired size but the program would crash due to bad memory access.
Once you do mylist.erase(i);, i is invalided, so your ++i in the loop is UB.
Your code should look like:
for (auto i = mylist.begin(); i != mylist.end() && i != prev(mylist.end()); /* Empty */)
{
if ((*i + *next(i)) % 2 == 0)
{
mylist.erase(next(i));
i = mylist.erase(i);
// maybe you want prev(i) if i != mylist.begin()
#ifdef DEBUG
std::cout << "this size " << mylist.size() << "\n";
for (const auto& e : myList) {
std::cout << e << " ";
}
std::cout << "\n";
#endif
count = std::min(count, step(myList));
} else {
++i;
}
}
In addition, final check should handle correctly when you remove last elements.
I am having issues with the following piece of code while using threads.
I read on the Microsoft site that appending to the concurrent_vector does not mess with iterators, so I did not provide and mutex for the duration of the find_if operation.
So the error I am receiving is an "Access violation"
I have 6 threads running concurrently. Should I wrap this in a mutex? Does it need one. I'm fairly new to C++.
std::stringstream key;
key << "SearchString " << ID << ", " << "Options" << ", " << Date;
auto &it = std::find_if(
m_spList.begin(), m_spList.end(),
[&key] (std::unique_ptr<IBaseObject>const &bo){
return bo->ID() == key.str();
}
);
if (it != m_spList.end()) {
while (it != m_spList.end()) {
ReplacePartResult* rpr = dynamic_cast<ReplacePartResult*>(it->get());
if (rpr) {
if (rpr->ReplaceItem) {
replaceBOMID = rpr->BOMID > 0 ? rpr->BOMID : 0;
if (_parentPart) {
_parentPart->TemplateBomID = rpr->BOMID;
_parentPart->Name = rpr->Name;
_parentPart->Description = rpr->Description;
}
}
}
it = std::find_if(
++it, m_spList.end(),
[&key](std::unique_ptr<IBaseObject>const &bo){
return bo->ID() == key.str();
}
);
}
}
Not 100% why, but i re-factored the find_if into a new function and explicitly defined my iterator type and it seems to be behaving. Maybe sening the stringstream into the lambda was the issue?
concurrency::concurrent_vector<std::unique_ptr<IBaseObject>>::iterator IBaseObject_FindKey(concurrency::concurrent_vector<std::unique_ptr<IBaseObject>>& mv, std::string const& _key)
{
return std::find_if(std::begin(mv), std::end(mv), [&_key](std::unique_ptr<IBaseObject>const &bo){return bo->ID() == _key; });
}
I'm using this function to find value in vector.
void program_data::find_curlAccountdata(int world, std::wstring login, std::wstring pass, curl_accounts & tmp){
std::unordered_map <int, std::vector<curl_accounts> > &t = curl_accountsdata; //world
std::vector<curl_accounts> &b = t[world];
std::vector<curl_accounts>::iterator & it = std::find_if(b.begin(), b.end(), [login, pass](curl_accounts& s) { return (s.name == login && s.pass == pass); });
if (it != b.end()){
tmp = *it;
}
}
And curl_accounts is struct.
Now when I edit some value in the struct in one place, and try to check it in second place it not the same.
So could you fix my function?
EDIT::
curl_accounts tmp,tmp2;
program_data::getInstance().find_curlAccountdata(server, login, pass, tmp);
tmp.logged = true;
std::cout << "TMP LOGGED: "<< tmp.logged<<std::endl; // return true
program_data::getInstance().find_curlAccountdata(server, login, pass, tmp2);
std::cout << "TMP 2 LOGGED: " << tmp2.logged << std::endl; // return false
std::cout << "sth";
You need a reference to a pointer. Try changing your signature to use curl_accounts *& tmp, instead of curl_accounts &tmp.
I have the following method in my program.
Weird thing is the data is not removed after I call erase.
Any idea?
map<int,obj>::iterator it = this->indexMap.find(id);
if(it != this->indexMap.end())
{
int mapSize = this->indexMap.size();
int dataSize = (*it).second.getDataMap().size();
//copy data to another node | even when it doesn't get into this if condition, it does not remove the data
if(mapSize> 1 && dataSize != 0)
{
it++;
this->copyData(id,it->first);
it--;
}
//remove peer | i've tried id and it, both does not work
this->indexMap.erase(it);
map<int,obj>::iterator iter = this->indexMap.find(id);
if(iter == this->indexMap.end())
{
cout << "ERROR" << endl;
}
}
Output:
ERROR
Thanks! :)
This block:
map<int,obj>::iterator iter = this->indexMap.find(id);
if(iter == this->indexMap.end())
{
cout << "ERROR" << endl;
}
prints out ERROR if an element with key id is not found in the map. Hence it has been removed.