在函數 f(Monitor*) 中宣告 static Monitor2 mon(a),傳入區域變數 Monitor m 的位址。多次呼叫 f(&m) 時,Monitor::i 的值異常增長;單次呼叫或呼叫無參數 f()(使用全域 monitor)則正常。
#include <iostream>
using namespace std;
class Monitor {
int i;
public:
Monitor() { i = 0; cout << "Monitor 建構:i=" << i << endl; }
~Monitor() { cout << "Monitor 解構:i=" << i << endl; }
void print() { cout << " " << i << endl; }
};
class Monitor2 {
Monitor* mon;
public:
Monitor2(Monitor* a) : mon(a) { cout << "Monitor2 建構 "; mon->print(); }
~Monitor2() { cout << "Monitor2 解構 "; mon->print(); }
};
void f(Monitor* a) { static Monitor2 mon(a); }
void main() {
Monitor m;
cout << "ok1" << endl;
f(&m);
cout << "ok2" << endl;
}
關鍵時序:
main() 結束時,區域變數 m 先被釋放、呼叫 ~Monitor()mon 才被解構,呼叫 ~Monitor2()Monitor2::mon 指標指向已被銷毀的 m 記憶體區域mon->print() 讀取懸空指標,輸出隨機垃圾值main() 執行期間: 棧區:m (Monitor) ← 靜態區:mon (Monitor2) 持有 &m main() 返回前: 1. m 解構 → 記憶體釋放/覆寫 2. mon 解構 → 嘗試存取已失效的 &m → 未定義行為
void f(Monitor* a) {
Monitor2 mon(a); // 非 static,隨函數結束銷毀,早於 m 解構
}
#include <memory>
void f(std::shared_ptr<Monitor> a) {
static std::shared_ptr<Monitor2> mon = std::make_shared<Monitor2>(a.get());
// 靜態 shared_ptr 延長 Monitor 生命週期至程式結束
}
若 Monitor2 需長期存在,應持有 Monitor 的擁有權(由值、unique_ptr 或 shared_ptr 管理),而非觀察者指標。
shared_ptr/weak_ptr)明確擁有權語意C++ 物件生命週期管理是資源洩漏、崩潰的高發區。建議深入學習 RAII(資源獲取即初始化)模式、智慧指標語意、以及 C++ 物件模型的記憶體佈局。