您好,登錄后才能下訂單哦!
C++調試記錄和心得有哪些,相信很多沒有經驗的人對此束手無策,為此本文總結了問題出現的原因和解決方法,通過這篇文章希望你能解決這個問題。
一、環境搭建
本人使用的是CentOS 7系統,該系統默認的g++版本不支持c++17的新特性。所以,首先需要做的就是升級新版本的g++。
1.到ftp://ftp.mirrorservice.org/sites/sourceware.org/pub/gcc/releases/網站上選擇支持c++17的gcc版本,并使用wget下載到Linux系統中:wget ftp://ftp.mirrorservice.org/sites/sourceware.org/pub/gcc/releases/gcc-7.1.0/gcc-7.1.0.tar.bz2
2.安裝編譯gcc需要的依賴包 sudo yum install gmp-devel mpfr-devel libmpc-devel -y
3.解壓gcc壓縮包到temp文件夾 tar -jxf gcc-7.1.0.tar.bz2 -C temp
4.進入到temp/gcc目錄下,執行 gcc ./configure --enable-checking=release --enable-languages=c,c++ --disable-multilib && make 進行gcc的編譯(這個步驟耗時較長)
5.安裝新版gcc sudo make install
6.由于在./configure階段未指定安裝路徑,那么新版的gcc的默認安裝位置就是/usr/local/目錄下,修改標準庫的軟連接使其指向新版本的標準庫 sudo ln -sf /usr/local/lib64/libstdc++.so.6.0.23 /lib64/libstdc++.so.6
7.需要使用c++17的特性時,需要在Makefile的CXXFLAGS變量中添加 -std=c++17
gdb默認情況下是不支持c++容器輸出的,不過在gdb 7.0版本之后,可以通過添加插件的方式來支持c++容器輸出
1.檢查gdb版本 gdb --version, (如果版本號低于7.0就不用往下看了)
2.在當前用戶的home目錄中(如/home/sxhlinux)下載 插件代碼 svn co svn://gcc.gnu.org/svn/gcc/trunk/libstdc++-v3/python (沒有svn的,需要通過 sudo yum install svn -y 安裝)然后執行mv python .gdb_stl 將該文件夾重命名(使其隱藏)
3.執行 vim ~/.gdbinit,編輯gdb配置文件,添加如下內容
add-auto-load-safe-path /usr/local/lib64/libstdc++.so.6.0.23-gdb.py #文件的版本號,根據這個目錄中的實際文件版本號確定
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 調試示例
1.下面的代碼是將帶有數字特征的分詞(用unorder_map保存),按照一定的規則(分詞的數字特征)進行合并
#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 ---------- */
2. 編譯該文件,提示 31行
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。
3.將報錯的這一行注釋掉,然后用gdb查看下pre->first和token->first的具體類型。具體如下
(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(也就無法進行+=,=等相關操作)。
4.根據第三步的分析結果,要實現合并元素的效果,只能是將合并后的值作為一個新的pair插入到原來的map中,然后將原來的兩個pair刪除。代碼如下:
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給出的提示相當明顯,認真仔細閱讀大部分可以很快找出解決方案,剩余的一部分棘手問題可以借助搜索引擎。
看完上述內容,你們掌握C++調試記錄和心得有哪些的方法了嗎?如果還想學到更多技能或想了解更多相關內容,歡迎關注億速云行業資訊頻道,感謝各位的閱讀!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。