I'm getting valgrind errors from 2 contexts. This is the 1st. It claims I have uninitialised values but I don't see any. Please help me understand where it's telling me the problem lies:
valgrind --leak-check=yes --track-origins=yes ./Lab4 in62.txt actual.txt
==4041== Memcheck, a memory error detector
==4041== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==4041== Using Valgrind-3.11.0 and LibVEX; rerun with -h for copyright info
==4041== Command: ./Lab4 in62.txt actual.txt
==4041==
==4041== Conditional jump or move depends on uninitialised value(s)
==4041== at 0x409F2C: __gnu_cxx::__enable_if<std::__is_char<char>::__value, bool>::__type std::operator==<char>(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) (basic_string.h:4913)
==4041== by 0x40AE3F: bool std::operator!=<char, std::char_traits<char>, std::allocator<char> >(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) (basic_string.h:4950)
==4041== by 0x407FFD: Relation::join_createMap(std::deque<std::map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > > >, std::allocator<std::map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > > > > >&, std::vector<Relation, std::allocator<Relation> >&, Rule&, int&, bool&, bool&, Tuple const&, std::map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > > >&, std::vector<int, std::allocator<int> >&, std::vector<int, std::allocator<int> >&) (relation.cpp:317)
==4041== by 0x408F87: Relation::join(std::vector<Relation, std::allocator<Relation> >&, Rule&, std::vector<Rule, std::allocator<Rule> >&) (relation.cpp:438)
==4041== by 0x42069C: Database::ruleEvaluation(std::vector<Rule, std::allocator<Rule> >&, std::vector<Predicate, std::allocator<Predicate> >&, std::vector<Predicate, std::allocator<Predicate> >&, std::basic_ofstream<char, std::char_traits<char> >&) (database.cpp:77)
==4041== by 0x41FA97: Database::evaluate(std::vector<Predicate, std::allocator<Predicate> >&, std::vector<Predicate, std::allocator<Predicate> >&, std::vector<Rule, std::allocator<Rule> >&, std::vector<Predicate, std::allocator<Predicate> >&, std::basic_ofstream<char, std::char_traits<char> >&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) (database.cpp:12)
==4041== by 0x42822C: main (main.cpp:27)
==4041== Uninitialised value was created by a heap allocation
==4041== at 0x4C2C12F: operator new(unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==4041== by 0x41642A: __gnu_cxx::new_allocator<std::map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > > > >::allocate(unsigned long, void const*) (new_allocator.h:104)
==4041== by 0x414A62: std::allocator_traits<std::allocator<std::map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > > > > >::allocate(std::allocator<std::map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > > > >&, unsigned long) (alloc_traits.h:360)
==4041== by 0x411C7F: std::_Deque_base<std::map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > > >, std::allocator<std::map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > > > > >::_M_allocate_node() (stl_deque.h:601)
==4041== by 0x41553C: std::_Deque_base<std::map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > > >, std::allocator<std::map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > > > > >::_M_create_nodes(std::map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > > >**, std::map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > > >**) (stl_deque.h:726)
==4041== by 0x4129DE: std::_Deque_base<std::map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > > >, std::allocator<std::map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > > > > >::_M_initialize_map(unsigned long) (stl_deque.h:700)
==4041== by 0x40EB1F: std::_Deque_base<std::map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > > >, std::allocator<std::map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > > > > >::_Deque_base() (stl_deque.h:490)
==4041== by 0x40B337: std::deque<std::map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > > >, std::allocator<std::map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > > > > >::deque() (stl_deque.h:883)
==4041== by 0x408DC3: Relation::join(std::vector<Relation, std::allocator<Relation> >&, Rule&, std::vector<Rule, std::allocator<Rule> >&) (relation.cpp:425)
==4041== by 0x42069C: Database::ruleEvaluation(std::vector<Rule, std::allocator<Rule> >&, std::vector<Predicate, std::allocator<Predicate> >&, std::vector<Predicate, std::allocator<Predicate> >&, std::basic_ofstream<char, std::char_traits<char> >&) (database.cpp:77)
==4041== by 0x41FA97: Database::evaluate(std::vector<Predicate, std::allocator<Predicate> >&, std::vector<Predicate, std::allocator<Predicate> >&, std::vector<Rule, std::allocator<Rule> >&, std::vector<Predicate, std::allocator<Predicate> >&, std::basic_ofstream<char, std::char_traits<char> >&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) (database.cpp:12)
==4041== by 0x42822C: main (main.cpp:27)
[more errors]
==5323==
==5323==
==5323== HEAP SUMMARY:
==5323== in use at exit: 72,704 bytes in 1 blocks
==5323== total heap usage: 29,328 allocs, 29,327 frees, 3,430,706 bytes allocated
==5323==
==5323== LEAK SUMMARY:
==5323== definitely lost: 0 bytes in 0 blocks
==5323== indirectly lost: 0 bytes in 0 blocks
==5323== possibly lost: 0 bytes in 0 blocks
==5323== still reachable: 72,704 bytes in 1 blocks
==5323== suppressed: 0 bytes in 0 blocks
==5323== Reachable blocks (those to which a pointer was found) are not shown.
==5323== To see them, rerun with: --leak-check=full --show-leak-kinds=all
==5323==
==5323== For counts of detected and suppressed errors, rerun with: -v
==5323== ERROR SUMMARY: 309 errors from 2 contexts (suppressed: 0 from 0)
main.cpp:25-27
std::ofstream out;
std::string arg = std::string(argv[2]);
myDatabase.evaluate(myDatalogProgram.getFactsVector(),myDatalogProgram.getQueriesVector(),myDatalogProgram.getRulesVector(),myDatalogProgram.getSchemesVector(), out, arg);
join:
(relation.cpp:425 is line 6, std::deque<strPairMap> working_tuples_deque; from the following function)
Relation Relation::join(std::vector<Relation> &cur_relation_vector, Rule &cur_rule, std::vector<Rule> &rules_vector){
bool dup_scheme_params = false;
strIntMap new_scheme_map;
Scheme new_scheme;
join_MakeScheme(cur_relation_vector, dup_scheme_params, new_scheme_map, new_scheme);
std::deque<strPairMap> working_tuples_deque; //relation.cpp:425
std::deque<strPairMap> working_tuples_deque_final;
std::vector<int> grand_copy_vector;
for (int j = 0; j < cur_relation_vector.size(); j++){
for (auto &x: cur_relation_vector.at(j).tuple_set){
bool diff_id_found = false;
strPairMap temp_map;
std::vector<int> map_indeces_to_copy;
int added_to_vector = 0;
if (working_tuples_deque.size() == 0){
join_createFirstMap(grand_copy_vector, working_tuples_deque, temp_map, cur_relation_vector, added_to_vector, j, x);
}
else{
join_createMap(working_tuples_deque, cur_relation_vector, cur_rule, j, dup_scheme_params, diff_id_found, x, temp_map, map_indeces_to_copy, grand_copy_vector);
join_combinePrevMapsToCurMap(diff_id_found, map_indeces_to_copy, temp_map, grand_copy_vector, cur_relation_vector, working_tuples_deque,j);
}
}
}
join_removeUnworthyMaps(working_tuples_deque, working_tuples_deque_final, grand_copy_vector, new_scheme);
/* Create new relation with new properties */
Relation combo_relation(cur_rule.primary_predicate.getID(),new_scheme,{});
std::set<Tuple> temp_tuple_set;
for (auto& o: working_tuples_deque_final){
Tuple temp_tuple;
for (auto& z: o){
temp_tuple.push_back(z.second.first);
}
temp_tuple_set.insert(temp_tuple);
}
combo_relation.tuple_set = temp_tuple_set;
return combo_relation;
}
join_createMap:
void Relation::join_createMap(std::deque<strPairMap> &working_tuples_deque, std::vector<Relation> &cur_relation_vector, Rule &cur_rule, int &j, bool &dup_scheme_params, bool &diff_id_found, const Tuple &x, strPairMap &temp_map, std::vector<int> &map_indeces_to_copy, std::vector<int> &grand_copy_vector){
for (int l = 0; l < working_tuples_deque.size(); l++){
bool add_index_to_vector = true;
for (int k = 0; k < cur_relation_vector.at(j).scheme.size(); k++){
/* If curent scheme param k is found in map l in working deque */
if (working_tuples_deque.at(l).find(cur_relation_vector.at(j).scheme.at(k))->second.second != cur_relation_vector.at(j).name){ //relation.cpp:317
diff_id_found = true;
if (working_tuples_deque.at(l).find(cur_relation_vector.at(j).scheme.at(k)) != working_tuples_deque.at(l).end()){
std::string param_to_match = working_tuples_deque.at(l).find(cur_rule.predicate_vector.at(j).parameter_vector.at(k).toString())->second.first;
/* but if the values with the matching scheme params don't match.. */
if (param_to_match != x.at(k)){
add_index_to_vector = false;
}
}
}
std::pair<std::string, std::string> temp_pair("","");
temp_pair.first = x.at(k);
temp_pair.second = cur_relation_vector.at(j).name;
temp_map.emplace(cur_relation_vector.at(j).scheme.at(k), temp_pair);
}
if (add_index_to_vector == true || dup_scheme_params == false){
map_indeces_to_copy.push_back(l);
grand_copy_vector.push_back(l);
}
}
}
What type of variable isn't being initialized? How do we pinpoint it with the provided information?
Update:
I now realize that the problem lies in relation.cpp:317, within join_createMap:
if (working_tuples_deque.at(l).find(cur_relation_vector.at(j).scheme.at(k))->second.second != cur_relation_vector.at(j).name){...}
When I break things down:
for (int k = 0; k < cur_relation_vector.at(j).scheme.size(); k++){
/* If curent scheme param k is found in map l in working deque */
strPairMap::iterator compare_it = working_tuples_deque.at(l).find(cur_relation_vector.at(j).scheme.at(k));
std::pair<std::string,std::string> compare_pair = compare_it->second; // offending line
std::string compare_string = compare_pair.second;
if (compare_string != cur_relation_vector.at(j).name){...}
...
}
Valgrind targets this line:
std::pair<std::string,std::string> compare_pair = compare_it->second;
with all of the following errors:
Source and destination overlap in memcpy(0x5ea3040, 0x5b2c450, 95601552)
Invalid read of size 8
Conditional jump or move depends on uninitialised value(s)
Uninitialised value was created by a heap allocation
Conditional jump or move depends on uninitialised value(s)
Uninitialised value was created by a heap allocation
terminate called after throwing an instance of 'std::logic_error'
what(): basic_string::_M_construct null not valid
Process terminating with default action of signal 6 (SIGABRT)
The offending line # was relation.cpp:317, not main.cpp:27. (Valgrind traces from the source of the problem up to the broadest scope.) The find function sometimes returned working_tuples_deque.at(l).end(). The code then went on to access .end()'s second element, which is invalid. That is where the Valgrind error originates.
As for the solution, I first initialized a separate std::string (compare_string). I then used an if statement to only reassign compare_string if the find did not return an .end() iterator (i.e. if the find function actually found something).
Result:
std::string compare_string = "";
strPairMap::iterator compare_it = working_tuples_deque.at(l).find(cur_relation_vector.at(j).scheme.at(k));
if (compare_it != working_tuples_deque.at(l).end()){
std::pair<std::string,std::string> compare_pair = compare_it->second;
compare_string = compare_pair.second;
}
cred: all commentators
Related
I am having a data race problem on tbb::concurrent_queue. Here is the code, producer and consumer functions are running on separate threads:
tbb::concurrent_queue<std::string> valid_json_queue;
Consumer:
...
std::string valid_json;
while(1) {
while(valid_json_queue.try_pop(valid_json)) {
json_manager_.parseJson(valid_json);
}
json_manager_.persist();
std::this_thread::sleep_for(std::chrono::seconds(5));
}
...
Producer:
...read data from socket via boost async_read_some...
for(const auto& valid_json : valid_jsons) {
valid_json_queue.push(valid_json);
}
...
I have ran the code with -fsanitizer=thread. Here is the relevant part from the output:
WARNING: ThreadSanitizer: data race (pid=21801)
...
WARNING: ThreadSanitizer: data race (pid=21801)
Write of size 8 at 0x7f861e405c00 by main thread:
#0 tbb::detail::d2::micro_queue<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, tbb::detail::d1::cache_aligned_allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >::padded_page::padded_page() /usr/local/include/oneapi/tbb/detail/_concurrent_queue_base.h:80 (dropcopy_mysql_adapter+0x4b77c1)
#1 decltype (::new ((void*)(0)) tbb::detail::d2::micro_queue<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, tbb::detail::d1::cache_aligned_allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >::padded_page()) std::construct_at<tbb::detail::d2::micro_queue<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, tbb::detail::d1::cache_aligned_allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >::padded_page>(tbb::detail::d2::micro_queue<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, tbb::detail::d1::cache_aligned_allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >::padded_page*) /usr/local/include/c++/10.1.0/bits/stl_construct.h:97 (dropcopy_mysql_adapter+0x4b6c76)
#2 std::enable_if<std::__and_<std::__and_<std::__not_<std::allocator_traits<tbb::detail::d1::cache_aligned_allocator<tbb::detail::d2::micro_queue<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, tbb::detail::d1::cache_aligned_allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >::padded_page> >::__construct_helper<tbb::detail::d2::micro_queue<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, tbb::detail::d1::cache_aligned_allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >::padded_page>::type>, std::is_constructible<tbb::detail::d2::micro_queue<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, tbb::detail::d1::cache_aligned_allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >::padded_page> > >::value, void>::type std::allocator_traits<tbb::detail::d1::cache_aligned_allocator<tbb::detail::d2::micro_queue<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, tbb::detail::d1::cache_aligned_allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >::padded_page> >::_S_construct<tbb::detail::d2::micro_queue<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, tbb::detail::d1::cache_aligned_allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >::padded_page>(tbb::detail::d1::cache_aligned_allocator<tbb::detail::d2::micro_queue<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, tbb::detail::d1::cache_aligned_allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >::padded_page>&, tbb::detail::d2::micro_queue<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, tbb::detail::d1::cache_aligned_allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >::padded_page*) /usr/local/include/c++/10.1.0/bits/alloc_traits.h:259 (dropcopy_mysql_adapter+0x4b6cac)
#3 decltype (_S_construct({parm#1}, {parm#2})) std::allocator_traits<tbb::detail::d1::cache_aligned_allocator<tbb::detail::d2::micro_queue<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, tbb::detail::d1::cache_aligned_allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >::padded_page> >::construct<tbb::detail::d2::micro_queue<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, tbb::detail::d1::cache_aligned_allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >::padded_page>(tbb::detail::d1::cache_aligned_allocator<tbb::detail::d2::micro_queue<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, tbb::detail::d1::cache_aligned_allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >::padded_page>&, tbb::detail::d2::micro_queue<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, tbb::detail::d1::cache_aligned_allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >::padded_page*) /usr/local/include/c++/10.1.0/bits/alloc_traits.h:360 (dropcopy_mysql_adapter+0x4b5ab3)
#4 tbb::detail::d2::micro_queue<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, tbb::detail::d1::cache_aligned_allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >::prepare_page(unsigned long, tbb::detail::d2::concurrent_queue_rep<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, tbb::detail::d1::cache_aligned_allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >&, tbb::detail::d1::cache_aligned_allocator<tbb::detail::d2::micro_queue<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, tbb::detail::d1::cache_aligned_allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >::padded_page>, tbb::detail::d2::micro_queue<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, tbb::detail::d1::cache_aligned_allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >::padded_page*&) /usr/local/include/oneapi/tbb/detail/_concurrent_queue_base.h:123 (dropcopy_mysql_adapter+0x4b4466)
#5 void tbb::detail::d2::micro_queue<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, tbb::detail::d1::cache_aligned_allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >::push<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&>(unsigned long, tbb::detail::d2::concurrent_queue_rep<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, tbb::detail::d1::cache_aligned_allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >&, tbb::detail::d1::cache_aligned_allocator<tbb::detail::d2::concurrent_queue_rep<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, tbb::detail::d1::cache_aligned_allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > >&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) /usr/local/include/oneapi/tbb/detail/_concurrent_queue_base.h:149 (dropcopy_mysql_adapter+0x4b3123)
#6 void tbb::detail::d2::concurrent_queue<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, tbb::detail::d1::cache_aligned_allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >::internal_push<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&>(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) /usr/local/include/oneapi/tbb/concurrent_queue.h:177 (dropcopy_mysql_adapter+0x4b1b71)
#7 tbb::detail::d2::concurrent_queue<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, tbb::detail::d1::cache_aligned_allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >::push(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) /usr/local/include/oneapi/tbb/concurrent_queue.h:119 (dropcopy_mysql_adapter+0x4b0447)
#8 operator() /home/zhft_003/aydin_space/tools-dropcopy_mysql_adapter/client.cpp:81 (dropcopy_mysql_adapter+0x49e351)
#9 operator() /usr/local/include/boost/asio/detail/bind_handler.hpp:182 (dropcopy_mysql_adapter+0x4a3318)
#10 asio_handler_invoke<boost::asio::detail::binder2<Client::do_read()::<lambda(boost::system::error_code, size_t)>, boost::system::error_code, long unsigned int> > /usr/local/include/boost/asio/handler_invoke_hook.hpp:88 (dropcopy_mysql_adapter+0x4a2be0)
#11 invoke<boost::asio::detail::binder2<Client::do_read()::<lambda(boost::system::error_code, size_t)>, boost::system::error_code, long unsigned int>, Client::do_read()::<lambda(boost::system::error_code, size_t)> > /usr/local/include/boost/asio/detail/handler_invoke_helpers.hpp:54 (dropcopy_mysql_adapter+0x4a26ca)
#12 complete<boost::asio::detail::binder2<Client::do_read()::<lambda(boost::system::error_code, size_t)>, boost::system::error_code, long unsigned int> > /usr/local/include/boost/asio/detail/handler_work.hpp:501 (dropcopy_mysql_adapter+0x4a20d0)
#13 do_complete /usr/local/include/boost/asio/detail/reactive_socket_recv_op.hpp:145 (dropcopy_mysql_adapter+0x4a1447)
#14 boost::asio::detail::scheduler_operation::complete(void*, boost::system::error_code const&, unsigned long) /usr/local/include/boost/asio/detail/scheduler_operation.hpp:40 (dropcopy_mysql_adapter+0x41040a)
#15 boost::asio::detail::epoll_reactor::descriptor_state::do_complete(void*, boost::asio::detail::scheduler_operation*, boost::system::error_code const&, unsigned long) /usr/local/include/boost/asio/detail/impl/epoll_reactor.ipp:776 (dropcopy_mysql_adapter+0x4aae53)
#16 boost::asio::detail::scheduler_operation::complete(void*, boost::system::error_code const&, unsigned long) /usr/local/include/boost/asio/detail/scheduler_operation.hpp:40 (dropcopy_mysql_adapter+0x41040a)
#17 boost::asio::detail::scheduler::do_run_one(boost::asio::detail::conditionally_enabled_mutex::scoped_lock&, boost::asio::detail::scheduler_thread_info&, boost::system::error_code const&) /usr/local/include/boost/asio/detail/impl/scheduler.ipp:486 (dropcopy_mysql_adapter+0x413afc)
#18 boost::asio::detail::scheduler::run(boost::system::error_code&) /usr/local/include/boost/asio/detail/impl/scheduler.ipp:204 (dropcopy_mysql_adapter+0x413511)
#19 boost::asio::io_context::run() <null> (dropcopy_mysql_adapter+0x414000)
#20 main /home/zhft_003/aydin_space/tools-dropcopy_mysql_adapter/main.cpp:59 (dropcopy_mysql_adapter+0x40ace6)
Previous read of size 8 at 0x7f861e405c00 by thread T1:
#0 tbb::detail::d2::micro_queue_pop_finalizer<tbb::detail::d2::micro_queue<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, tbb::detail::d1::cache_aligned_allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, tbb::detail::d1::cache_aligned_allocator<tbb::detail::d2::micro_queue<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, tbb::detail::d1::cache_aligned_allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >::padded_page> >::~micro_queue_pop_finalizer() /usr/local/include/oneapi/tbb/detail/_concurrent_queue_base.h:382 (dropcopy_mysql_adapter+0x4b4b6b)
#1 tbb::detail::d2::micro_queue<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, tbb::detail::d1::cache_aligned_allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >::pop(void*, unsigned long, tbb::detail::d2::concurrent_queue_rep<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, tbb::detail::d1::cache_aligned_allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >&, tbb::detail::d1::cache_aligned_allocator<tbb::detail::d2::concurrent_queue_rep<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, tbb::detail::d1::cache_aligned_allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > >&) /usr/local/include/oneapi/tbb/detail/_concurrent_queue_base.h:188 (dropcopy_mysql_adapter+0x4b3479)
#2 tbb::detail::d2::concurrent_queue<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, tbb::detail::d1::cache_aligned_allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >::internal_try_pop(void*) /usr/local/include/oneapi/tbb/concurrent_queue.h:193 (dropcopy_mysql_adapter+0x4b1f26)
#3 tbb::detail::d2::concurrent_queue<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, tbb::detail::d1::cache_aligned_allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >::try_pop(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&) /usr/local/include/oneapi/tbb/concurrent_queue.h:135 (dropcopy_mysql_adapter+0x4b0629)
#4 Client::jsonParseLoop() /home/zhft_003/aydin_space/tools-dropcopy_mysql_adapter/client.cpp:124 (dropcopy_mysql_adapter+0x49e875)
#5 void std::__invoke_impl<void, void (Client::*)(), Client*>(std::__invoke_memfun_deref, void (Client::*&&)(), Client*&&) /usr/local/include/c++/10.1.0/bits/invoke.h:73 (dropcopy_mysql_adapter+0x4b941e)
#6 std::__invoke_result<void (Client::*)(), Client*>::type std::__invoke<void (Client::*)(), Client*>(void (Client::*&&)(), Client*&&) /usr/local/include/c++/10.1.0/bits/invoke.h:95 (dropcopy_mysql_adapter+0x4b92e2)
#7 void std::thread::_Invoker<std::tuple<void (Client::*)(), Client*> >::_M_invoke<0ul, 1ul>(std::_Index_tuple<0ul, 1ul>) /usr/local/include/c++/10.1.0/thread:264 (dropcopy_mysql_adapter+0x4b91f2)
#8 std::thread::_Invoker<std::tuple<void (Client::*)(), Client*> >::operator()() /usr/local/include/c++/10.1.0/thread:271 (dropcopy_mysql_adapter+0x4b9182)
#9 std::thread::_State_impl<std::thread::_Invoker<std::tuple<void (Client::*)(), Client*> > >::_M_run() /usr/local/include/c++/10.1.0/thread:215 (dropcopy_mysql_adapter+0x4b910c)
#10 execute_native_thread_routine ../../../.././libstdc++-v3/src/c++11/thread.cc:80 (libstdc++.so.6+0xcdd5f)
Thread T1 (tid=21803, running) created by main thread at:
#0 pthread_create ../../.././libsanitizer/tsan/tsan_interceptors_posix.cpp:962 (libtsan.so.0+0x58b22)
#1 __gthread_create /home/zhft_003/downloads/gcc/x86_64-pc-linux-gnu/libstdc++-v3/include/x86_64-pc-linux-gnu/bits/gthr-default.h:663 (libstdc++.so.6+0xcdfd4)
#2 std::thread::_M_start_thread(std::unique_ptr<std::thread::_State, std::default_delete<std::thread::_State> >, void (*)()) ../../../.././libstdc++-v3/src/c++11/thread.cc:135 (libstdc++.so.6+0xcdfd4)
#3 std::thread std::jthread::_S_create<void (Client::*)(), Client*>(std::stop_source&, void (Client::*&&)(), Client*&&) /usr/local/include/c++/10.1.0/thread:557 (dropcopy_mysql_adapter+0x4b1852)
#4 std::jthread::jthread<void (Client::*)(), Client*, void>(void (Client::*&&)(), Client*&&) /usr/local/include/c++/10.1.0/thread:455 (dropcopy_mysql_adapter+0x4b0031)
#5 Client::Client(boost::asio::io_context&, boost::asio::ip::basic_resolver_results<boost::asio::ip::tcp> const&) /home/zhft_003/aydin_space/tools-dropcopy_mysql_adapter/client.cpp:18 (dropcopy_mysql_adapter+0x49d8f8)
#6 main /home/zhft_003/aydin_space/tools-dropcopy_mysql_adapter/main.cpp:57 (dropcopy_mysql_adapter+0x40acd7)
client.cpp:124 is the line with while(valid_json_queue.try_pop(valid_json)), whereas client.cpp:81 is the line with valid_json_queue.push(valid_json);.
I thought I was safe using tbb::concurrent_queue in a multithreaded context but apparently I am doing something wrong here.
g++ version is 10.1.0
We observe data races when two or more threads in a single process access the same memory location concurrently.
Concurrent_queue doesn't create any parallelism at all: it just allows multiple threads to safely access the same queue. It ensures there are no race conditions.
We can use a mutex to synchronize the threads and to get rid of data race problems.
Refer to the below links for more details:
https://oneapi-src.github.io/oneTBB/main/tbb_userguide/Concurrent_Queue_Classes.html
https://spec.oneapi.io/versions/latest/elements/oneTBB/source/mutual_exclusion.html
Thanks & Regards,
Noorjahan.
Consider the following code snippet:
myEnum stringToEnum(const std::string& enumString) {
static const std::unordered_map<std::string, myEnum> conversionMap = {
{"enumA", myEnum::enumA},
{"enumB", myEnum::enumB},
{"enumC", myEnum::enumC}};
if(conversionMap.count(enumString) == 0) {
// Return some default value
}
return conversionMap.at(enumString);
}
void threadedFcn() {
// Do some things
for (int i = 0; i < someNumber; ++i) {
// Do some more things
auto myEnum = stringToEnum(myString);
// Do even more stuff
}
}
int main() {
threadedFcn(); // No problem
std::thread(threadedFcn).join(); // No problem
std::thread(threadedFcn).detach(); // Seg fault
}
A few things about this:
If I remove the call to count then it won't seg fault. It looks like it's caused by that somehow.
It only happens on Linux Debian 9 (I've built with Windows 10 and Mac as well).
If I add something like std::this_thread::sleep_for(std::chrono::milliseconds(2000)); after the detach call, then it won't seg fault.
If I make conversionMap not static, then it won't seg fault.
I can't figure out what the exact problem is, but it's something to do with the main thread exiting before the detached thread finishes.
As Slava correctly said, the problem is that you are letting the main return, while your other thread is running.
Returning from main eventually calls exit, which goes through all registered atexit handlers.
When using libstdc++ (and probably most other C++ runtime implementations), any static C++ object that has been constructed registers its destructor with atexit, so after that destructor fires, your detached thread is accessing destroyed conversionMap object, with predictable results.
You can observe this by using Address Sanitizer (-fsanitize=address), which reports:
=================================================================
==87625==ERROR: AddressSanitizer: heap-use-after-free on address 0x603000000010 at pc 0x563122b9c6c5 bp 0x7fc54eafea20 sp 0x7fc54eafea18
READ of size 8 at 0x603000000010 thread T2
#0 0x563122b9c6c4 in std::_Hashtable<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, myEnum>, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, myEnum> >, std::__detail
::_Select1st, std::equal_to<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::hash<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits<true, false, true>
>::_M_bucket_begin(unsigned long) const /usr/include/c++/9/bits/hashtable.h:943
#1 0x563122b9bcf2 in std::_Hashtable<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, myEnum>, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, myEnum> >, std::__detail
::_Select1st, std::equal_to<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::hash<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits<true, false, true>
>::count(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) const /usr/include/c++/9/bits/hashtable.h:1451
#2 0x563122b9b76e in std::unordered_map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, myEnum, std::hash<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::equal_to<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::ba
sic_string<char, std::char_traits<char>, std::allocator<char> > const, myEnum> > >::count(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) const /usr/include/c++/9/bits/unordered_map.h:939
#3 0x563122b9a793 in stringToEnum(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) /tmp/t.cc:16
#4 0x563122b9aa9c in threadedFcn() /tmp/t.cc:27
#5 0x563122b9f71e in void std::__invoke_impl<void, void (*)()>(std::__invoke_other, void (*&&)()) /usr/include/c++/9/bits/invoke.h:60
#6 0x563122b9f681 in std::__invoke_result<void (*)()>::type std::__invoke<void (*)()>(void (*&&)()) /usr/include/c++/9/bits/invoke.h:95
#7 0x563122b9f5cb in void std::thread::_Invoker<std::tuple<void (*)()> >::_M_invoke<0ul>(std::_Index_tuple<0ul>) /usr/include/c++/9/thread:244
#8 0x563122b9f56c in std::thread::_Invoker<std::tuple<void (*)()> >::operator()() /usr/include/c++/9/thread:251
#9 0x563122b9f4ed in std::thread::_State_impl<std::thread::_Invoker<std::tuple<void (*)()> > >::_M_run() /usr/include/c++/9/thread:195
#10 0x7fc552301baf (/usr/lib/x86_64-linux-gnu/libstdc++.so.6+0xcebaf)
#11 0x7fc55202bf26 in start_thread /build/glibc-M65Gwz/glibc-2.30/nptl/pthread_create.c:479
#12 0x7fc5521532ee in __clone (/lib/x86_64-linux-gnu/libc.so.6+0xfd2ee)
0x603000000010 is located 0 bytes inside of 24-byte region [0x603000000010,0x603000000028)
freed by thread T0 here:
#0 0x7fc552509f97 in operator delete(void*) (/usr/lib/x86_64-linux-gnu/libasan.so.5+0x109f97)
#1 0x563122b9e5fb in __gnu_cxx::new_allocator<std::__detail::_Hash_node_base*>::deallocate(std::__detail::_Hash_node_base**, unsigned long) /usr/include/c++/9/ext/new_allocator.h:128
#2 0x563122b9dbf5 in std::allocator_traits<std::allocator<std::__detail::_Hash_node_base*> >::deallocate(std::allocator<std::__detail::_Hash_node_base*>&, std::__detail::_Hash_node_base**, unsigned long) /usr/include/c++/9/bits/alloc_traits.h:470
#3 0x563122b9d0cc in std::__detail::_Hashtable_alloc<std::allocator<std::__detail::_Hash_node<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, myEnum>, true> > >::_M_deallocate_buckets(std::__detail::_Hash_node_base**, unsigned long) /usr/include/c++/9/bits/hashtable_policy.h:2148
#4 0x563122b9c5d3 in std::_Hashtable<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, myEnum>, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, myEnum> >, std::__detail
::_Select1st, std::equal_to<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::hash<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits<true, false, true>
>::_M_deallocate_buckets(std::__detail::_Hash_node_base**, unsigned long) /usr/include/c++/9/bits/hashtable.h:370
#5 0x563122b9bc99 in std::_Hashtable<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, myEnum>, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, myEnum> >, std::__detail
::_Select1st, std::equal_to<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::hash<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits<true, false, true>
>::_M_deallocate_buckets() /usr/include/c++/9/bits/hashtable.h:375
#6 0x563122b9b73b in std::_Hashtable<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, myEnum>, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, myEnum> >, std::__detail
::_Select1st, std::equal_to<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::hash<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits<true, false, true>
>::~_Hashtable() /usr/include/c++/9/bits/hashtable.h:1353
#7 0x563122b9b4ff in std::unordered_map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, myEnum, std::hash<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::equal_to<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::ba
sic_string<char, std::char_traits<char>, std::allocator<char> > const, myEnum> > >::~unordered_map() /usr/include/c++/9/bits/unordered_map.h:102
#8 0x7fc552093e26 in __run_exit_handlers /build/glibc-M65Gwz/glibc-2.30/stdlib/exit.c:108
previously allocated by thread T0 here:
#0 0x7fc55250919f in operator new(unsigned long) (/usr/lib/x86_64-linux-gnu/libasan.so.5+0x10919f)
#1 0x563122b9e828 in __gnu_cxx::new_allocator<std::__detail::_Hash_node_base*>::allocate(unsigned long, void const*) /usr/include/c++/9/ext/new_allocator.h:114
#2 0x563122b9defc in std::allocator_traits<std::allocator<std::__detail::_Hash_node_base*> >::allocate(std::allocator<std::__detail::_Hash_node_base*>&, unsigned long) /usr/include/c++/9/bits/alloc_traits.h:444
#3 0x563122b9d6d4 in std::__detail::_Hashtable_alloc<std::allocator<std::__detail::_Hash_node<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, myEnum>, true> > >::_M_allocate_buckets(unsigned long) /usr/include/c++/9/bits/hashtable_policy.h:2134
#4 0x563122b9ce5b in std::_Hashtable<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, myEnum>, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, myEnum> >, std::__detail
::_Select1st, std::equal_to<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::hash<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits<true, false, true>
>::_M_allocate_buckets(unsigned long) /usr/include/c++/9/bits/hashtable.h:361
#5 0x563122b9c3db in std::_Hashtable<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, myEnum>, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, myEnum> >, std::__detail
::_Select1st, std::equal_to<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::hash<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits<true, false, true>
>::_Hashtable<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, myEnum> const*>(std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, myEnum> const*, std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, myEnum> const*, unsigned l
ong, std::hash<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > const&, std::__detail::_Mod_range_hashing const&, std::__detail::_Default_ranged_hash const&, std::equal_to<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > const&, std::__detail::_Select1st const&, std::allocator<std::pair<std::__cxx
11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, myEnum> > const&) /usr/include/c++/9/bits/hashtable.h:989
#6 0x563122b9bab5 in std::_Hashtable<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, myEnum>, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, myEnum> >, std::__detail
::_Select1st, std::equal_to<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::hash<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits<true, false, true>
>::_Hashtable(std::initializer_list<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, myEnum> >, unsigned long, std::hash<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > const&, std::equal_to<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > const&,
std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, myEnum> > const&) /usr/include/c++/9/bits/hashtable.h:466
#7 0x563122b9b6a3 in std::unordered_map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, myEnum, std::hash<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::equal_to<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::ba
sic_string<char, std::char_traits<char>, std::allocator<char> > const, myEnum> > >::unordered_map(std::initializer_list<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, myEnum> >, unsigned long, std::hash<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > const&, std::equal_to<std::__
cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > const&, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, myEnum> > const&) /usr/include/c++/9/bits/unordered_map.h:231
#8 0x563122b9a678 in stringToEnum(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) /tmp/t.cc:14
#9 0x563122b9aa9c in threadedFcn() /tmp/t.cc:27
#10 0x563122b9ac0f in main /tmp/t.cc:33
#11 0x7fc55207ce0a in __libc_start_main ../csu/libc-start.c:308
Thread T2 created by T0 here:
#0 0x7fc5524399b2 in pthread_create (/usr/lib/x86_64-linux-gnu/libasan.so.5+0x399b2)
#1 0x7fc552301e24 in std::thread::_M_start_thread(std::unique_ptr<std::thread::_State, std::default_delete<std::thread::_State> >, void (*)()) (/usr/lib/x86_64-linux-gnu/libstdc++.so.6+0xcee24)
#2 0x563122b9ac75 in main /tmp/t.cc:35
#3 0x7fc55207ce0a in __libc_start_main ../csu/libc-start.c:308
Update:
I guess an easy fix is to just make my variable not-static (functionally it will be the same but with an obvious performance hit).
There is an easy way to avoid having to construct a new unordered_map on every call, while also avoiding the global destruction problem: use a static pointer:
myEnum stringToEnum(const std::string& enumString) {
static const auto *conversionMap =
new std::unordered_map<std::string, myEnum>{
{"enumA", myEnum::enumA},
{"enumB", myEnum::enumB},
{"enumC", myEnum::enumC}
};
if (conversionMap->count(enumString) == 0) {
// Return some default value
}
return conversionMap->at(enumString);
}
I have a problem with the following code, which I derived from my actual code to create a minimal example. It contains some container class, which holds a pointer to some base class. When I create an object from the derived class (which inherits from the base class) and hand it over to a container object everything seems to work fine. But when I call a method of the container object which then calls a method from the base class where I want to perform some operations of the base classes private member (which is a map) and want to return a modified map, I get a SIGSEGV. There seems to be a problem in returning something, because the print-method works fine.
#include <iostream>
#include <map>
class Base {
public:
Base() { _m_parameters.clear(); };
void parameters(const std::map <std::string, double> &m_parameters) { _m_parameters = m_parameters; };
std::map <std::string, double> get() {
std::map <std::string, double> new_map;
for(const std::pair <const std::string, double> &p : _m_parameters)
new_map.insert(std::make_pair(p.first, p.second));
return new_map;
};
void print() {
for(const std::pair <const std::string, double> &p : _m_parameters)
std::cout << p.first << ": " << p.second << "\n";
std::cout << "\n";
};
private:
std::map <std::string, double> _m_parameters;
};
class Derived : public Base {
public:
Derived() : Base() {
std::map <std::string, double> m_parameter;
for(int i = 0; i < 3; ++i) {
std::string s_name = "param_" + std::to_string(i);
auto p = (double) i;
m_parameter.insert(std::make_pair(s_name, p));
}
Base::parameters(m_parameter);
};
};
class Container {
public:
Container() { _base = nullptr; };
explicit Container(Base base) { _base = &base; };
void do_stuff() {
std::map <std::string, double> map;
_base -> print();
map = _base -> get();
for(const std::pair <const std::string, double> &p : map)
std::cout << p.first << ": " << p.second << "\n";
}
private:
Base *_base;
};
int main(int argc, char** argv) {
Derived derived = Derived();
Container container = Container(derived);
container.do_stuff();
return 0;
}
Simply running under Valgrind reveals that you're accessing memory that you freed:
==10852== Invalid read of size 8
==10852== at 0x49B05B0: std::basic_ostream<char, std::char_traits<char> >& std::operator<< <char, std::char_traits<char>, std::allocator<char> >(std::basic_ostream<char, std::char_traits<char> >&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.28)
==10852== by 0x10B8FA: Base::print() (58131198.cpp:20)
==10852== by 0x10BB66: Container::do_stuff() (58131198.cpp:52)
==10852== by 0x10B327: main (58131198.cpp:65)
==10852== Address 0x4d84128 is 40 bytes inside a block of size 72 free'd
==10852== at 0x4836EAB: operator delete(void*) (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==10852== by 0x10E8A5: __gnu_cxx::new_allocator<std::_Rb_tree_node<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, double> > >::deallocate(std::_Rb_tree_node<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, double> >*, unsigned long) (new_allocator.h:128)
==10852== by 0x10E5A6: std::allocator_traits<std::allocator<std::_Rb_tree_node<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, double> > > >::deallocate(std::allocator<std::_Rb_tree_node<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, double> > >&, std::_Rb_tree_node<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, double> >*, unsigned long) (alloc_traits.h:470)
==10852== by 0x10DDF0: std::_Rb_tree<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, double>, std::_Select1st<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, double> >, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, double> > >::_M_put_node(std::_Rb_tree_node<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, double> >*) (stl_tree.h:584)
==10852== by 0x10D17B: std::_Rb_tree<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, double>, std::_Select1st<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, double> >, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, double> > >::_M_drop_node(std::_Rb_tree_node<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, double> >*) (stl_tree.h:651)
==10852== by 0x10C875: std::_Rb_tree<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, double>, std::_Select1st<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, double> >, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, double> > >::_M_erase(std::_Rb_tree_node<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, double> >*) (stl_tree.h:1915)
==10852== by 0x10C0C1: std::_Rb_tree<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, double>, std::_Select1st<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, double> >, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, double> > >::~_Rb_tree() (stl_tree.h:995)
==10852== by 0x10B701: std::map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, double, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, double> > >::~map() (stl_map.h:300)
==10852== by 0x10B973: Base::~Base() (58131198.cpp:4)
==10852== by 0x10B31B: main (58131198.cpp:64)
==10852== Block was alloc'd at
==10852== at 0x4835DEF: operator new(unsigned long) (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==10852== by 0x10EAF5: __gnu_cxx::new_allocator<std::_Rb_tree_node<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, double> > >::allocate(unsigned long, void const*) (new_allocator.h:114)
==10852== by 0x10E662: std::allocator_traits<std::allocator<std::_Rb_tree_node<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, double> > > >::allocate(std::allocator<std::_Rb_tree_node<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, double> > >&, unsigned long) (alloc_traits.h:444)
==10852== by 0x10DEAA: std::_Rb_tree<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, double>, std::_Select1st<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, double> >, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, double> > >::_M_get_node() (stl_tree.h:580)
==10852== by 0x10EA7F: std::_Rb_tree_node<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, double> >* std::_Rb_tree<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, double>, std::_Select1st<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, double> >, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, double> > >::_M_create_node<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, double> const&>(std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, double> const&) (stl_tree.h:630)
==10852== by 0x10EC4E: std::_Rb_tree_node<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, double> >* std::_Rb_tree<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, double>, std::_Select1st<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, double> >, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, double> > >::_Alloc_node::operator()<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, double> const&>(std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, double> const&) const (stl_tree.h:548)
==10852== by 0x10E73B: std::_Rb_tree_node<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, double> >* std::_Rb_tree<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, double>, std::_Select1st<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, double> >, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, double> > >::_M_clone_node<std::_Rb_tree<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, double>, std::_Select1st<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, double> >, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, double> > >::_Alloc_node>(std::_Rb_tree_node<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, double> > const*, std::_Rb_tree<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, double>, std::_Select1st<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, double> >, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, double> > >::_Alloc_node&) (stl_tree.h:658)
==10852== by 0x10E19F: std::_Rb_tree_node<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, double> >* std::_Rb_tree<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, double>, std::_Select1st<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, double> >, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, double> > >::_M_copy<std::_Rb_tree<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, double>, std::_Select1st<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, double> >, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, double> > >::_Alloc_node>(std::_Rb_tree_node<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, double> > const*, std::_Rb_tree_node_base*, std::_Rb_tree<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, double>, std::_Select1st<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, double> >, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, double> > >::_Alloc_node&) (stl_tree.h:1887)
==10852== by 0x10D784: std::_Rb_tree_node<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, double> >* std::_Rb_tree<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, double>, std::_Select1st<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, double> >, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, double> > >::_M_copy<std::_Rb_tree<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, double>, std::_Select1st<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, double> >, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, double> > >::_Alloc_node>(std::_Rb_tree<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, double>, std::_Select1st<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, double> >, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, double> > > const&, std::_Rb_tree<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, double>, std::_Select1st<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, double> >, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, double> > >::_Alloc_node&) (stl_tree.h:901)
==10852== by 0x10CE3D: std::_Rb_tree<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, double>, std::_Select1st<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, double> >, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, double> > >::_M_copy(std::_Rb_tree<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, double>, std::_Select1st<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, double> >, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, double> > > const&) (stl_tree.h:912)
==10852== by 0x10C440: std::_Rb_tree<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, double>, std::_Select1st<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, double> >, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, double> > >::_Rb_tree(std::_Rb_tree<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, double>, std::_Select1st<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, double> >, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, double> > > const&) (stl_tree.h:950)
==10852== by 0x10BCCE: std::map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, double, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, double> > >::map(std::map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, double, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, double> > > const&) (stl_map.h:205)
==10852==
There's plenty more of these use-after-free errors, so I suggest fixing them all before further debugging.
The simple fix is to pass base by reference when constructing a Container:
explicit Container(Base& base) : _base{&base} {}
With that change, it's Valgrind-clean.
I am trying to compile tokumx (mongodb fork with transactions) on mavericks. It compiles for some time and then errors out with this message:
Linking build/darwin/64/release/mongo/mongodump
Undefined symbols for architecture x86_64:
"std::tr1::hash<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >::operator()(std::basic_string<char, std::char_traits<char>, std::allocator<char> >) const", referenced from:
std::tr1::_Hashtable<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::pair<std::basic_string<char, std::char_traits<char>, std::allocator<char> > const, boost::function<mongo::Status (std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)> >, std::allocator<std::pair<std::basic_string<char, std::char_traits<char>, std::allocator<char> > const, boost::function<mongo::Status (std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)> > >, std::_Select1st<std::pair<std::basic_string<char, std::char_traits<char>, std::allocator<char> > const, boost::function<mongo::Status (std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)> > >, std::equal_to<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::tr1::hash<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::tr1::__detail::_Mod_range_hashing, std::tr1::__detail::_Default_ranged_hash, std::tr1::__detail::_Prime_rehash_policy, false, false, true>::find(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) const in configuration_variable_manager.o
std::tr1::_Hashtable<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::pair<std::basic_string<char, std::char_traits<char>, std::allocator<char> > const, boost::function<mongo::Status (std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)> >, std::allocator<std::pair<std::basic_string<char, std::char_traits<char>, std::allocator<char> > const, boost::function<mongo::Status (std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)> > >, std::_Select1st<std::pair<std::basic_string<char, std::char_traits<char>, std::allocator<char> > const, boost::function<mongo::Status (std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)> > >, std::equal_to<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::tr1::hash<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::tr1::__detail::_Mod_range_hashing, std::tr1::__detail::_Default_ranged_hash, std::tr1::__detail::_Prime_rehash_policy, false, false, true>::_M_rehash(unsigned long) in configuration_variable_manager.o
std::tr1::__detail::_Map_base<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::pair<std::basic_string<char, std::char_traits<char>, std::allocator<char> > const, boost::function<mongo::Status (std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)> >, std::_Select1st<std::pair<std::basic_string<char, std::char_traits<char>, std::allocator<char> > const, boost::function<mongo::Status (std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)> > >, true, std::tr1::_Hashtable<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::pair<std::basic_string<char, std::char_traits<char>, std::allocator<char> > const, boost::function<mongo::Status (std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)> >, std::allocator<std::pair<std::basic_string<char, std::char_traits<char>, std::allocator<char> > const, boost::function<mongo::Status (std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)> > >, std::_Select1st<std::pair<std::basic_string<char, std::char_traits<char>, std::allocator<char> > const, boost::function<mongo::Status (std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)> > >, std::equal_to<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::tr1::hash<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::tr1::__detail::_Mod_range_hashing, std::tr1::__detail::_Default_ranged_hash, std::tr1::__detail::_Prime_rehash_policy, false, false, true> >::operator[](std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) in configuration_variable_manager.o
mongo::InitializerDependencyGraph::addInitializer(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, boost::function<mongo::Status (mongo::InitializerContext*)> const&, std::vector<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::basic_string<char, std::char_traits<char>, std::allocator<char> > > > const&, std::vector<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::basic_string<char, std::char_traits<char>, std::allocator<char> > > > const&) in initializer_dependency_graph.o
"std::__detail::_List_node_base::_M_unhook()", referenced from:
mongo::DistributedLockPinger::_distLockPingThread(mongo::ConnectionString, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, unsigned long long) in distlock.o
std::list<mongo::FieldRangeSetPair, std::allocator<mongo::FieldRangeSetPair> >::_M_erase(std::_List_iterator<mongo::FieldRangeSetPair>) [clone .isra.535] in queryutil.o
mongo::OrRangeGenerator::_popOrClause(mongo::FieldRangeSet const*, mongo::Collection*, int, mongo::BSONObj const&) in queryutil.o
mongo::OrRangeGenerator::popOrClauseSingleKey() in queryutil.o
mongo::threadpool::ThreadPool::task_done(mongo::threadpool::Worker*) in thread_pool.o
mongo::threadpool::ThreadPool::~ThreadPool() in thread_pool.o
mongo::threadpool::ThreadPool::~ThreadPool() in thread_pool.o
...
ld: symbol(s) not found for architecture x86_64
Anyone knows exactly whats going on there?
This is caused by a mismatch between the standard library headers and library version, it's similar to this report http://gcc.gnu.org/bugzilla/show_bug.cgi?id=43882.
OSX compilation isn't strictly supported for TokuMX yet, but I've been working on it recently. Make sure you have the latest Xcode and command line tools installed, and try compiling again with --cc=cc --cxx="c++ -std=c++11 -stdlib=libc++" as arguments to scons.
If that doesn't work, please also provide the command you used to try to build, and all of the preceding output, this would be a question better suited to the mailing list I think.
for C++ basic types, it works
unordered_map<string, int> m;
unordered_map<string, int>::iterator itr;
string s;
itr = m.find(s);
It compiles with no problem.
However, when I try
unordered_map<set<string>, int> m;
unordered_map<set<string>, int>::iterator itr;
set<string> s;
itr = m.find(s);
The compiler complains something that I can't read. Does anyone know what is going on? Do I have to use exception here?
g++ output:
/tmp/ccdwrdVP.o: In function `std::__detail::_Hash_code_base<std::set<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::less<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::basic_string<char, std::char_traits<char>, std::allocator<char> > > >, std::pair<std::set<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::less<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::basic_string<char, std::char_traits<char>, std::allocator<char> > > > const, int>, std::_Select1st<std::pair<std::set<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::less<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::basic_string<char, std::char_traits<char>, std::allocator<char> > > > const, int> >, std::equal_to<std::set<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::less<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::basic_string<char, std::char_traits<char>, std::allocator<char> > > > >, std::hash<std::set<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::less<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::basic_string<char, std::char_traits<char>, std::allocator<char> > > > >, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, false>::_M_hash_code(std::set<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::less<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::basic_string<char, std::char_traits<char>, std::allocator<char> > > > const&) const':
test_unordermap_find.cpp:(.text._ZNKSt8__detail15_Hash_code_baseISt3setISsSt4lessISsESaISsEESt4pairIKS5_iESt10_Select1stIS8_ESt8equal_toIS5_ESt4hashIS5_ENS_18_Mod_range_hashingENS_20_Default_ranged_hashELb0EE12_M_hash_codeERS7_[std::__detail::_Hash_code_base<std::set<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::less<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::basic_string<char, std::char_traits<char>, std::allocator<char> > > >, std::pair<std::set<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::less<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::basic_string<char, std::char_traits<char>, std::allocator<char> > > > const, int>, std::_Select1st<std::pair<std::set<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::less<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::basic_string<char, std::char_traits<char>, std::allocator<char> > > > const, int> >, std::equal_to<std::set<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::less<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::basic_string<char, std::char_traits<char>, std::allocator<char> > > > >, std::hash<std::set<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::less<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::basic_string<char, std::char_traits<char>, std::allocator<char> > > > >, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, false>::_M_hash_code(std::set<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::less<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::basic_string<char, std::char_traits<char>, std::allocator<char> > > > const&) const]+0x37): undefined reference to `std::hash<std::set<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::less<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::basic_string<char, std::char_traits<char>, std::allocator<char> > > > >::operator()(std::set<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::less<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::basic_string<char, std::char_traits<char>, std::allocator<char> > > >) const'
collect2: ld returned 1 exit status
std::unordered_map is implemented by means of a hash table, so it needs a hash function that can be applied to its key type. The default hash function is the std::hash template:
template < class Key,
class T,
class Hash = std::hash<Key>,
class Pred = std::equal_to<Key>,
class Alloc = std::allocator< std::pair<const Key,T> >
> class unordered_map;
However, std::hash is not defined for std::set. Therefore you need to either provide a definition of std::hash<set<string>>, or else specify your own hash function using the third template parameter of unordered_map.