1

I'm using the asio networking library. I'm seeing a very strange behaviour where the debugger tells me that the call to std::map::at() throws an out_of_range exception, however I have catch block to catch precisely that type of exception!

The map in question is this:

/*Both of these maps are global variables in the namespace cloud*/
map<string, weak_ptr<session> > cloud::services;
map<string, vector<weak_ptr<session> > > cloud::subscribed; //this one

And the code that's throwing the exception is this:

void session::subscribirse(std::string a_which)
{
  try
  {
    //We obtain a reference to the group of sockets subscribed to this service name
    vector<weak_ptr<session>>& grupo = cloud::subscribed.at(a_which);   //HERE
    grupo.emplace_back(shared_from_this() );
  }
  catch(out_of_range& e) //The group didn't exist (no-one had subscribed to it yet)
  {
    vector<weak_ptr<session>> new_group;
    new_group.emplace_back(shared_from_this());
    cloud::subscribed.emplace(make_pair(a_which, new_group));
  }
  catch(...)
  {
    cout << "unexpected exception during subscribe\n";
  }
  subscriptions_.emplace_back(a_which);
  consumed_ = true;
}

Could the catch-block be rethrowing and the debugger not being capable of detecting that? (I really don't think so).

Sorry if question is not clear, I've spent the last 6 hours and I'm feeling desperate.

sehe
  • 374,641
  • 47
  • 450
  • 633
Turambar
  • 153
  • 11
  • From the code shown here, I would say that the `catch` block should work. There is nothing in the `catch` block that could rethrow `std::out_of_range`. – zett42 May 28 '17 at 19:49
  • Well. Check namespace collisions (spell it out as `catch (::std::out_of_range const&e)` e.g.). Next up, rebuild every part of the program and dependencies with _exactly_ the same compiler flags. Make sure `nube::suscritos` is _actually_ of type `::std::map<...>` – sehe May 28 '17 at 19:55
  • @JamesPoag makes a valid point: how certain are you that your assumptions are valid? Can you debug trace when compiling without optimization? – sehe May 29 '17 at 01:07
  • Also try a `catch(std::exception& e2)` between your two existing catches, and print out `e2.what()`. – aschepler May 29 '17 at 01:22
  • Changing out_of_range& to std::out_of_range const& did make a difference, the exception gets caught now. Was it ignoring the exception thrown because I was catching non-const exceptions? And why did (...) not catch it? – Turambar May 29 '17 at 05:18
  • Sigh... nevermind, the error still appeared after data from a serial port came to the socket, so probably garbage values corrupt somehow the logic my program uses. Anyway, using `find()` to determine if value is present is not subject to those errors, and is by far the best solution. Thanks for your time, though I'm still perplexed at that strange behavior. – Turambar May 29 '17 at 06:43
  • Oh. In that case, your whole question is misguided. See https://en.wikipedia.org/wiki/Undefined_behavior – sehe May 30 '17 at 22:40

1 Answers1

0

The [] operator will insert an empty value if it doesn't already exist and doesn't throw.

cloud::subscribed[a_which].emplace_back(shared_from_this() );

You can check for the existence of a key using find():

if(cloud::subscribed.find(a_which) != cloud::subscribed.end())

Finally, how certain are you that it's throwing an out of bounds exception and not another exception?

sehe
  • 374,641
  • 47
  • 450
  • 633
James Poag
  • 2,320
  • 1
  • 13
  • 20
  • 3
    "How certain?" - About [5/7 prolly](http://en.cppreference.com/w/cpp/container/map/at) o.O – sehe May 28 '17 at 23:04
  • I can see how the phrasing has confused you. Yes, at() throws `out of bounds`, but if the other catch is being triggered, then how certain are you that it's an `out of bounds` exception? There is more code in the `try` block than dreamt of [...], Horatio. – James Poag May 29 '17 at 00:15
  • @JamesPoag Thanks for the tip James, the alternative using `find()` is more clear and easier to maintain. Sehe's suggestion to explicitly name `std::out_of_range const&` caused the exceptions to be caught. I'm still puzzled since (...) is supposed to catch everything. I'm doing a lot of low level IO so maybe this was undefined behaviour? – Turambar May 29 '17 at 05:34
  • @Turambar you are clearly seeing namespace collisions/hiding there. See https://stackoverflow.com/questions/1452721/why-is-using-namespace-std-considered-bad-practice – sehe May 30 '17 at 22:39