首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計疑難解答

C++ 函數中建立指針:delete 後仍能輸出、輸出局部變數地址解析

     編輯:程式設計疑難解答

問題代碼片段

void func() {
    int *ps = new int(10);
    delete[] ps; // 錯誤:應用 delete,非 delete[]
    cout << *ps; // 輸出 10(未定義行為)
}

void func2() {
    int *p = new int(20);
    cout << &p; // 輸出 p 的地址(棧地址),而非指向的堆地址
}

現象一:delete[] ps 後仍能輸出原值

原因

  • delete[](或 delete)釋放記憶體回收給堆管理器,但不會清零或擦除記憶體內容。
  • 該記憶體區塊在被重新分配或覆寫前,原始位元組仍保留,因此解引用「懸空指標」可能仍讀到舊值。
  • 此為未定義行為 (UB),不可依賴。不同編譯器、優化等級、執行環境下結果可能不同(崩潰、輸出亂碼、看似正常)。

正確做法

delete ps;        // 單一物件用 delete
ps = nullptr;     // 置空,避免誤用懸空指標

現象二:cout << &p 輸出不變的棧地址

原因

  • p 是函數內的局部指標變數,儲存於棧上。
  • &p 取得的是指標變數本身的地址(棧地址),而非 p 指向的堆記憶體地址(即 p 的值)。
  • 函數每次調用,p 在棧幀中的相對位置固定,故 &p 輸出相同(或極接近)。

正確觀察指向的堆地址

cout << p;      // 輸出指標值,即堆地址
cout << &*p;    // 等價於 p,解引用再取址

記憶體模型圖解


棧
+------------------+
| 函數參數/返回位址 |
+------------------+
| 局部變數 p  ------|-----> 指向
+------------------+       |
                            v
堆                    +----------+
                        | int(20)  |  <-- p 的值 (堆地址)
                        +----------+

總結

  1. delete 釋放記憶體但不清零,懸空指標解引用屬 UB,務必置 nullptr。
  2. &p 是指標變數本身的棧地址;p 才是指向的堆地址。
  3. 嚴格區分指標變數地址與指標指向的地址,避免除錯誤判。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved