0

I am storing a bunch of dummy objects in an unordered_map, and then iterating through to delete them. Somehow, it comes out with a key value pairing where the value is a null pointer, even though I'm pretty sure that is not possible.

Each of the objects that I make just houses a part of a very large string that I construct randomly. I make sure to hand the constructor of this object at least 5 characters of the string.

Here is the code:

Delete Function

bool delete_objects(){
    Serial.println("deleting objects in 'store'");
    for(auto iter = store.begin(); iter != store.end(); iter++)
    {
        Serial.println("\nDeleting the following element: \n");
        Serial.print("Key: ");
        Serial.println(iter->first);
        delay(1000);
        Serial.print("Value: ");
        Serial.println(iter->second->ShowMeWhatYouGot());
        delay(1000);

        delete iter->second;
        iter->second = nullptr;
        store.erase(iter);
    } 

    if(store.empty())
       return true;
    else
       return false;
}

block where objects are allocated (delete_objects() is called right before this)

unsigned int index = 0;
unsigned int key = 0;
while(index < buff_string.length()){
    int amount = (rand() % 51) + 5;
    DummyClass* dc = new DummyClass(buff_string.substr(index, amount));
    store[key] = dc;
    index += amount;
    key++;
    Serial.println("Created new DummyClass object");
    Serial.print("Free Memory: ");
    Serial.println(System.freeMemory());
}

class definition

using namespace std;

class DummyClass {
    private:
        char* _container;

    public:
        DummyClass(){
        }

        DummyClass(string input){
            _container = new char[input.length()];
            strcpy(_container, input.c_str());
        }

        ~DummyClass(){
            delete _container;
            _container = nullptr;
        }

        char* ShowMeWhatYouGot(){
            return _container;
        }
};

Serial Output, it SOS's (crashes, for a particle chip) when key is 0

Key: 194 Value: q->@B{s?tX/miN3K?[~2[mvTOSKPE34#5[@q8*d8BZwH`

Deleting the following element:

Key: 193 Value: 9Hb^7-J(#z3H#0uqg

Deleting the following element:

Key: 192 Value: V$xZ>C$u{MjxzxL?{KQqvQp*MN3~Ce&yZbmop1$9xlkJM)jGja~P{mY

Deleting the following element:

Key: 191 Value: yo*CVzE~2

Deleting the following element:

Key: 190 Value: [&PQakTV3{^Aq?(ffV/*24xaXej]~T1^SfWiM3ATpk#{CoQ

Deleting the following element:

Key: 0 Value

Community
  • 1
  • 1
bgenchel
  • 3,739
  • 4
  • 19
  • 28
  • Possible duplicate of [What happens if you call erase() on a map element while iterating from begin to end?](http://stackoverflow.com/questions/263945/what-happens-if-you-call-erase-on-a-map-element-while-iterating-from-begin-to) – Basilevs Oct 15 '15 at 04:28

1 Answers1

2

From http://en.cppreference.com/w/cpp/container/unordered_map/erase

References and iterators to the erased elements are invalidated. Other iterators and references are not invalidated.

After

    store.erase(iter);

iter is invalid. The expression ++iter after that is cause for undefined behavior.

One way to solve the problem:

for(auto iter = store.begin(); iter != store.end(); /* iter++ */)
                                                    // Not needed
{
    // code
    // ...

    iter = store.erase(iter);
} 

Another way to solve the problem:

for(auto iter = store.begin(); iter != store.end(); iter++)
{
    // code
    // ...

    // Dont' call erase.
    // store.erase(iter);
} 

// Clear the map.
store.clear();
R Sahu
  • 204,454
  • 14
  • 159
  • 270