一次C++调试记录
add-auto-load-safe-path /usr/local/lib64/libstdc++.so.6.0.23-gdb.py #文件的版本号,根据这个目录中的实际文件版本号确定 python import sys sys.path.append("/usr/local/share/gcc-7.1.0/python") sys.path.insert(0, '/home/sxhlinux/.gdb_stl') #注:将第二个参数中的路径改成自己的.gdb_stl文件夹路径 from libstdcxx.v6.printers import register_libstdcxx_printers register_libstdcxx_printers (None) end二、gdb 调试示例
#include <iostream> #include <cstdlib> #include <map> #include <unordered_map> using namespace std; template <typename T1, typename T2> bool merge_tokens(T1 &target, const T2 &rules) { auto pre = target.begin(); for (auto token = target.begin(); token != target.end(); ) { if (pre == token) { token ++; continue; } auto range = rules.equal_range(pre->second); auto it = range.first; for (; it != range.second; it++) { if (it->second == token->second) { break; } } if (it == range.second) { pre = token; token ++; } else { pre->first += token->first; // target.insert(std::make_pair<typename T1::key_type, typename T1::mapped_type>(pre->first + token->first, 16)); pre->second = 16; token = target.erase(token); pre = token; } } } int main ( int argc, char *argv[] ) { unordered_map<string, size_t> tokens = {{"def", 22}, {"ghi", 100}, {"abc", 22}}; unordered_multimap<size_t, size_t> rules = {{22, 100}, {100, 22}, {1, 38}}; merge_tokens(tokens, rules); return EXIT_SUCCESS; } /* ---------- end of function main ---------- */
test.cpp:31:15: error: passing ‘const std::__cxx11::basic_string<char>’ as ‘this’ argument discards qualifiers [-fpermissive] pre->first += token->first; ~~~~~~~~~~~^~~~~~~~~~~~~~ /usr/local/include/c++/7.1.0/bits/basic_string.h:1122:7: note: in call to ‘std::__cxx11::basic_string<_CharT, _Traits, _Alloc>& std::__cxx11::basic_string<_CharT, _Traits, _Alloc>::operator+=(const std::__cxx11::basic_string<_CharT, _Traits, _Alloc>&) [with _CharT = char; _Traits = std::char_traits<char>; _Alloc = std::allocator<char>]’ operator+=(const basic_string& __str) ^~~~~~~~根据错误提示:string 的运算符 += 要求参数是一个 const string类型(作为右值,非const类型也可以作为const类型的参数使用),返回值是一个string类型。再看 出错的语句pre->first += token->first; 根据mian函数中的tokens的定义,token和pre的first成员都应该是string而不是const string。
(gdb) whatis target type = std::unordered_map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, unsigned long> & (gdb) whatis target.begin() type = std::unordered_map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, unsigned long, 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::basic_string<char, std::char_traits<char>, std::allocator<char> > const, unsigned long> > >::iterator (gdb) whatis pre type = std::__detail::_Node_iterator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, unsigned long>, false, true>根据上面显示的,target两个参数类型确实和定义的一样,string和unsigned long;target.begin()类型说明中的std::allocator的模板参数pair的第一个参数为 string const,说明在创建unordered_map时,key的类型为const string而不是string(猜测这跟map与key相关的只有增加、删除而没有修改操作有关)。因为allocator在申请空间时,已经隐式的将string转成了const string,所以,pre->first的类型是const string而不是string(也就无法进行+=,=等相关操作)。
target.insert(std::make_pair<typename T1::key_type, typename T1::mapped_type>(pre->first + token->first, 16)); target.erase(pre); token = target.erase(token); pre = token;三、总结 很多时候我们遇到问题首先想到的是将错误复制下来,然后粘贴到google搜索框中,漫无目的的去寻找答案,而不是仔细分析查看gcc给出的错误提示。跟我的经验,很多时候gcc给出的提示相当明显,认真仔细阅读大部分可以很快找出解决方案,剩余的一部分棘手问题可以借助搜索引擎(PS:当搜索英文提示时,如果没有google,可以使用英文版的必应,效果也不错) 优质内容筛选与推荐>>