首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> C >> 關於C

C 語言遞歸缺失 return 的隱患:從匯編看返回值機制

     編輯:關於C

現象重現

遞歸函數 Add_Recursion 計算位運算加法,基礎情況 return a,遞歸情況卻漏寫 return 直接調用自身。神奇的是 Add_Recursion(1,1) 仍正確輸出 2。但若在遞歸返回後調用任意函數(如 changestack()),結果變為 3(即 changestack 的返回值)。

根本原因:返回值傳遞靠 EAX 寄存器

x86 呼叫慣例中,整型返回值放在 EAX。遞歸最深層 return a 執行 mov eax, a,隨後各層 ret 時若無賦值指令,EAX 保持不變,主函數讀到正確值。但中間層若調用其他函數,EAX 被覆蓋,導致錯誤傳遞。

反匯編證據

  • changestack 編譯為 mov eax, 3; ret。
  • 主函數調用後直接 mov [num], eax 取返回值。
  • 遞歸函數無 return 時,編譯器不生成 mov eax, ...,僅 ret。

驗證實驗:內聯匯編修改 EAX

__asm { mov eax, 3 } // 在遞歸返回後插入
// 主函數將打印 3,證明返回值確實取自 EAX。

編譯器警告與最佳實踐

MSVC 警告 C4715:「非所有控制路徑都返回值」。C++ 更嚴格直接報錯。結論:所有分支必須顯式 return,切勿依賴寄存器殘值,否則代碼極不穩定,微小修改即導致錯誤。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved