1

Consider this code:

#include <iostream>
#include <string>
#include <map>

int  main()
{
  std::map<std::string, std::string>  map = {
    { "ghasem", "another" }
  };
  std::cout << map.find("another")->second << std::endl;
  std::cout << map.size() << std::endl;
}

It will be compiled and run successfully(the process return value is 0), but we couldn't see the output of map.size(). Neither -fsanitize=address nor -fsanitize=undfined reports any problem. I compiled with GCC-11.2.1 and Clang-13.0.0, both are the same. And running the code step by step using GDB-11.1-5 will not help and all the steps will be run successfully.

But if I reorder the last two lines:

#include <iostream>
#include <string>
#include <map>

int  main()
{
  std::map<std::string, std::string>  map = {
    { "ghasem", "another" }
  };
  std::cout << map.size() << std::endl;
  std::cout << map.find("another")->second << std::endl;
}

I will get a Segmentation Fault and now ASAN could report the error.


And my question here is: Is the code cause some sort of Undefined Behavior? How could I detect those errors?


Environment:
  • OS: Fedora 35
  • Compiler(s):
    • GCC 11.2.1
    • Clang 13.0.0
  • Additional Compiler Flags:
  • Debugger: GDB 11.1-5
Ghasem Ramezani
  • 2,683
  • 1
  • 13
  • 32
  • 5
    `` is not something you should be including yourself. If you want `std::map`, that properly comes from ``. – Karl Knechtel Jan 23 '22 at 11:10
  • Does this answer your question? [Checking if an iterator is valid](https://stackoverflow.com/questions/2062956/checking-if-an-iterator-is-valid) – Karl Knechtel Jan 23 '22 at 11:10
  • 4
    [Why should I not #include ?](https://stackoverflow.com/questions/31816095/why-should-i-not-include-bits-stdc-h) Any resource teaching you to use it should be shunned like the plague. If you truly want to learn programming and C++, please invest in [some good books](https://stackoverflow.com/questions/31816095/why-should-i-not-include-bits-stdc-h) and perhaps even take classes. – Some programmer dude Jan 23 '22 at 11:10
  • Compile first code with -O2 and `-fsanitize=address` throws something. – kiner_shah Jan 23 '22 at 11:10
  • @Someprogrammerdude, That is just for simplifying the code snippet. – Ghasem Ramezani Jan 23 '22 at 12:33

1 Answers1

6

There is no key comparing equal to "another" in the map. Therefore map.find("another") will return the .end() iterator of the map. Dereferencing this iterator in ->second is then undefined behavior since end iterators may not be dereferenced.

Your code should check that the iterator returned from find is not the end iterator, i.e. that an element has been found.

In terms of debugging, if you are using libstdc++ as standard library implementation (which is the case with GCC and potentially with Clang), you can use -D_GLIBCXX_DEBUGon the compiler invocation to enable debug assertions in the standard library implementation which will detect this issue.

user17732522
  • 53,019
  • 2
  • 56
  • 105