From 399f3966949451f7c0536fca364a155473a4e158 Mon Sep 17 00:00:00 2001 From: TermiNexus Date: Thu, 8 Oct 2026 22:27:47 +0800 Subject: [PATCH] =?UTF-8?q?test(lifetime):=20=E4=BF=AE=E6=AD=A3=20CaseRais?= =?UTF-8?q?eCaught=20=E7=9A=84=20dtor=20=E8=AE=A1=E6=95=B0=E6=97=B6?= =?UTF-8?q?=E6=9C=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 对象属于本函数,释放发生在函数返回那一刻;原用例在自己体内 return 之前就检查 dtor_hits,计数必然还没变,恒判 rc=1。拆出 CaseRaiseCaughtInner,把计数检查移到调用方(与 CaseRaiseExit 同口径)。 --- NewLifetimeTest/App/main.vp | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/NewLifetimeTest/App/main.vp b/NewLifetimeTest/App/main.vp index d46625b..8f6d7ea 100644 --- a/NewLifetimeTest/App/main.vp +++ b/NewLifetimeTest/App/main.vp @@ -156,9 +156,11 @@ def CaseRaiseExit() -> int: return 0 -# 对照:异常被**本函数**捕获时不得提前释放(对象在 except 体里仍可用),出口才释放 -def CaseRaiseCaught() -> int: - before: int = dtor_hits +# 对照:异常被**本函数**捕获时不得提前释放(对象在 except 体里仍可用),出口才释放。 +# 注意:释放发生在**被调函数返回那一刻**,所以 dtor 计数必须在**调用方**检查—— +# 在被调函数自己体内、return 之前检查(原写法)计数必然还没变,恒判失败(测试自身的 bug, +# 与 CaseRaiseExit 的差别正在于那边对象属于被调函数)。 +def CaseRaiseCaughtInner() -> int: ok: int = 0 try: p: DtorPoint* = new heap slife DtorPoint(6) @@ -167,7 +169,14 @@ def CaseRaiseCaught() -> int: # 对象必须**还活着**:若编译器在 raise 处就释放了,这里就是 use-after-free if p.x == 6: ok = 1 if ok == 0: return 2 - if dtor_hits != before + 1: return 1 # 只在函数出口释放一次 + return 0 + + +def CaseRaiseCaught() -> int: + before: int = dtor_hits + rc: int = CaseRaiseCaughtInner() + if rc != 0: return rc + if dtor_hits != before + 1: return 1 # 内部函数出口恰好释放一次 return 0