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
CodePudding user response:
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.
