Search code examples
c++crashmultimapstdadvance

std::advance of std::multimap end() iterator by negative number crashes


My app crashed on this operation:

std::multimap<int, std::string, std::greater<int>> mm;
// insert elements
auto it = mm.end();
std::advance(it, -(mm.size() - 7));

Here is the message of crash:

Expression: map/set iterator not incrementable

What is the problem?

EDIT: When I wrote just -1 instead of -(mm.size() - 7) it did not crash, why? Please consider that when I debug mm.size() is 8.

EDIT 2: When I write std::advance(it, -(static_cast<int>(scoresMap.size()) - 7)); it works. It is because of the size type of the multimap, but still cannot guess what is the reason.


Solution

  • The expresion (mm.size() - 7) produces an unsigned value, std::size_t. The unsigned value is then negated, and according to recent C++ draft spec (N3690):

    The operand of the unary - operator shall have arithmetic or unscoped enumeration type and the result is the negation of its operand. Integral promotion is performed on integral or enumeration operands. The negative of an unsigned quantity is computed by subtracting its value from 2n, where n is the number of bits in the promoted operand. The type of the result is the type of the promoted operand.

    the value being provided to std::advance could be converted to some value larger than mm.size() due to the negation rules of unsigned types.

    The second expression in your edit, static_cast<int>(scoresMap.size() - 7), changes the value to a signed type, int. Negating that value will get the desired value, however, the static_cast has undefined behavior if scoresMap.size() - 7 returns a value larger than std::numeric_limits<int>::max().