看板 C_and_CPP 關於我們 聯絡資訊
開發平台(Platform): (Ex: Win10, Linux, ...) Linux 編譯器(Ex: GCC, clang, VC++...)+目標環境(跟開發平台不同的話需列出) GCC 問題(Question): 最近除錯時發現 gdb 好像無法解析 auto 的類別成員函式回傳值 一律只會印出 void 而且有確定該函式沒被優化掉 程式碼(Code):(請善用置底文網頁, 記得排版,禁止使用圖檔) 簡單例子如下: #include <cstdio> struct S { auto f1(int v) { return v; } int f2(int v) { return v; } }; auto f3(int v) { return v; } int main() { S s; printf("%d %d %d\n", s.f1(1), s.f2(1), f3(1)); // 1 1 1 } 使用 gdb 印出如下: (gdb) p s.f1(1) $1 = void (gdb) p s.f2(1) $2 = 1 (gdb) p f3(1) $3 = 1 從結果看來一般函式 f3() 用 auto 回傳就沒這個問題 有人知道原因嗎? -- ※ 發信站: 批踢踢實業坊(ptt.cc), 來自: 140.112.30.51 (臺灣) ※ 文章網址: https://www.ptt.cc/bbs/C_and_CPP/M.1602904834.A.69F.html
ucrxzero: https://i.imgur.com/H7CzftL.png 10/17 12:15
ucrxzero: 版本多少 ? 10/17 12:15
KaryuuIssen: GDB 7.7.1 跟SO上這個好像是不同問題 10/17 12:26
ucrxzero: 感覺要用很髒的寫法印出來 10/17 13:21
ucrxzero: 按錯等補推 10/17 13:21
ucrxzero: 1.0 10/17 13:25
這串我也有爬到 但沒任何實質解答XD
ucrxzero: 可以用-O0編嗎 最不會有問題? 10/17 13:35
跟優化應該無關 至少我看有無 auto 生出來的程式段組語是一樣的
ucrxzero: https://i.imgur.com/E8qFr2J.png 10/17 13:37
ucrxzero: 這是gdb evaluate function的過程 10/17 13:38
ucrxzero: 我大膽猜測問題在create new stack那邊 10/17 13:38
ucrxzero: 畢竟全域不在stack裡面 10/17 13:38
ucrxzero: 所以全域的沒問題 10/17 13:44
一開始跟你想的一樣是 gdb 的問題 但剛剛我突然想到 看了一下 f1() 和 f3() 的 .debug_info 段發現: f1() ------------------------------------------------------------------------------ <2><672>: Abbrev Number: 26 (DW_TAG_subprogram) <673> DW_AT_external : 1 <673> DW_AT_name : f1 <676> DW_AT_decl_file : 1 <677> DW_AT_decl_line : 19 <678> DW_AT_linkage_name: (indirect string, offset: 0x249): _ZN1S2f1Ei <67c> DW_AT_type : <0x6b1> <680> DW_AT_declaration : 1 <680> DW_AT_object_pointer: <0x688> <684> DW_AT_sibling : <0x693> ... <1><6b1>: Abbrev Number: 29 (DW_TAG_unspecified_type) <6b2> DW_AT_name : (indirect string, offset: 0x106): auto f3() ------------------------------------------------------------------------------ <1><5e>: Abbrev Number: 4 (DW_TAG_base_type) <5f> DW_AT_byte_size : 4 <60> DW_AT_encoding : 5 (signed) <61> DW_AT_name : int ... <1><735>: Abbrev Number: 34 (DW_TAG_subprogram) <736> DW_AT_external : 1 <736> DW_AT_name : f3 <739> DW_AT_decl_file : 1 <73a> DW_AT_decl_line : 24 <73b> DW_AT_linkage_name: (indirect string, offset: 0xf9): _Z2f3i <73f> DW_AT_type : <0x5e> <743> DW_AT_low_pc : 0x400536 <74b> DW_AT_high_pc : 0xc <753> DW_AT_frame_base : 1 byte block: 9c (DW_OP_call_frame_cfa) <755> DW_AT_GNU_all_call_sites: 1 <755> DW_AT_sibling : <0x766> 我把重點上色了 同樣都是 auto f1() 卻無從推導出是回傳 int? 看來是 DWARF 生成的問題? 所以 gdb 無法解讀只能回傳 void 嗎 不知道有沒有理解正確
ucrxzero: 好想知道為什麼喔 10/17 15:33
ucrxzero: 用print S::f1 卻可以有int 10/17 16:21
ucrxzero: 我今天有空幫你研究一下 10/17 16:25
ucrxzero: 我用template卻可以s.f1(123)=123 10/17 16:45
剛試了一下 S::f1 確實能出現 int ... template 如果不行的話這個問題應該早就很多人討論了XD 畢竟 auto 回傳型別在 C++14 才支援
ucrxzero: 11就有囉 10/17 17:23
ucrxzero: 只是要配合decltype 10/17 17:26
a1u1usul3: 隨手試了一下,clang9編出來跑gdb是有推論出來的 10/19 17:05
a1u1usul3: clang9編出來debug info直接就填int囉 10/19 17:19
ucrxzero: 乾 10/19 18:08
ucrxzero: 打錯 10/19 18:08
感謝 剛試了一下 clang 真的OK了 看來就是 gcc 的 DWARF 生成的問題... 本來想說要去回報 gcc bug 的 發現原來幾年前已經有人回報過 只是遲遲未處理: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=78329 直到半年前又有相同的回報: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94459 這次就有處理了 已經修掉的樣子 之後新版的 gcc 應該就不會有問題了
ucrxzero: 跟我想的一樣 10/20 10:20
ucrxzero: 舊的版本可以試試看把回傳值改成volatile試試 10/20 11:27
ucrxzero: 剛剛想到的 10/20 11:27
一樣不行 添加 CV 看來只是多一層繞道而已 auto 終究未解析出來
ucrxzero: 抱歉 10/20 15:18
幹嘛道歉XD 還要感謝你一直推幫我高調 ※ 編輯: KaryuuIssen (140.112.30.51 臺灣), 10/21/2020 05:28:55