user1124236
user1124236

Reputation: 503

accessing value in map of maps

typedef std::vector<UCHAR> RESPONSE_BUFFER;
typedef TimedHashMap<int, RESPONSE_BUFFER*> TimeResponseHashMap;

Inner map prototype has "integer" as key and "pointer to a vector of chars" as mapped value.

TimeResponseHashMap* inner_pending_response_map;

Outer map is a map of maps. it has "integer" as key and "pointer to inner map" as mapped value.

std::map<int, TimeResponseHashMap* > outer_pending_response_map;

I insert like this: Inner map is a userdefined map, hence it has a different format.

inner_pending_response_map->Insert((int)s16MessageID, &resp_buffer, expirytime);

outer_pending_response_map.insert(make_pair((int)s16SessionID,       
    inner_pending_response_map));

TimeResponseHashMap provides the user defined interface "Find" to access members of the map.

template <typename Key, typename ElementObject>
THM_ERROR TimedHashMap<Key, ElementObject>::Find(const Key& k, ElementObject& e)
{

    typename hash_map<Key, BaseElement_*, dw_hash<Key>, dw_equal_to<Key> >::iterator itr;
    try
    {
        itr = h_->find(k);
    } catch ( ... )
    {
        return E_INTERNAL_ERROR;
    }

    if ( itr == h_->end() )
    {
        e = NULL;
        return E_ITEM_NOT_FOUND;
    }

    e = itr->second->e_;
    return E_SUCCESS;
}

I have both the keys and now I need to access the "mapped value" of the inner map. The inner map uses the above Find() function to search. I need to pass RESPONSE_BUFFER variable as the second parameter to the Find() function.

I'm trying to extract like this which gives a wrong output:

RESPONSE_BUFFER resp_buffer;
ExtractFragmentResponse(u16Key1, u16Key2, &resp_buffer);

Definition of ExtractFragmentResponse is below:

STATUS
C_THREAD::ExtractFragmentResponse(USHORT u16SessionID, USHORT u16MessageID, 
RESPONSE_BUFFER* resp)
{
      (((outer_pending_response_map.find(u16SessionID))->second)->Find((int)u16MessageID, resp))
}

resp is not giving me correct data. How can it be done?

Upvotes: 0

Views: 519

Answers (1)

PaulMcKenzie
PaulMcKenzie

Reputation: 35440

This may not directly answer the question, but it does bring up why the code used is highly faulty and should be broken up into several lines.

STATUS
C_THREAD::ExtractFragmentResponse(USHORT u16SessionID, USHORT u16MessageID, 
RESPONSE_BUFFER* resp)
{
  (((outer_pending_response_map.find(u16SessionID))->second)->Find((int)u16MessageID, resp))
}

Let's say this did actually "work". There is a major problem with it, regardless. The issue is this:

outer_pending_response_map.find(u16SessionID)

What happens if find doesn't find the entry u16SessionID? You now have been returned outer_pending_response_map.end(). When this return value is used like this:

outer_pending_response_map.end()->second

boom, your dead. That line attempts to use an invalid iterator, which is undefined behavior.

What you should do is this:

 std::map<int, TimeResponseHashMap* >::iterator it1 = outer_pending_response_map.find(u16SessionID);
 if ( it1 != outer_pending_response_map.end())
     (it1->second)->Find((int)u16MessageID, resp);
 else
 {
    // you  fill in what happens if the find fails
 }

To debug your issue, you can then further break up the lines to ensure what you're getting is valid:

 std::map<int, TimeResponseHashMap* >::iterator it1 = outer_pending_response_map.find(u16SessionID);
 if ( it1 != outer_pending_response_map.end())
 {
     TimeResponseHashMap *theMap = it1->second;
     theMap->Find((int)u16MessageID, resp);
 } 
 else
 {
    // you  fill in what happens if the find fails
 }

The code above saves it1->second to a value (theMap) that you can inspect easily to see if it is correct.

Upvotes: 1

Related Questions