Skip to content

Commit 571671f

Browse files
authored
Merge pull request #62191 from mikeash/deinit-escape-assert
[Runtime] Fatal error if self escapes from deinit.
2 parents 62b26b1 + 108f780 commit 571671f

File tree

2 files changed

+34
-0
lines changed

2 files changed

+34
-0
lines changed

stdlib/public/runtime/HeapObject.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -710,6 +710,13 @@ void swift::swift_rootObjCDealloc(HeapObject *self) {
710710
void swift::swift_deallocClassInstance(HeapObject *object,
711711
size_t allocatedSize,
712712
size_t allocatedAlignMask) {
713+
size_t retainCount = swift_retainCount(object);
714+
if (SWIFT_UNLIKELY(retainCount > 1))
715+
swift::fatalError(0,
716+
"Object %p deallocated with retain count %zd, reference "
717+
"may have escaped from deinit.\n",
718+
object, retainCount);
719+
713720
#if SWIFT_OBJC_INTEROP
714721
// We need to let the ObjC runtime clean up any associated objects or weak
715722
// references associated with this object.
@@ -718,6 +725,7 @@ void swift::swift_deallocClassInstance(HeapObject *object,
718725
#else
719726
const bool fastDeallocSupported = true;
720727
#endif
728+
721729
if (!fastDeallocSupported || !object->refCounts.getPureSwiftDeallocation()) {
722730
objc_destructInstance((id)object);
723731
}

test/Runtime/deinit_escape.swift

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
// RUN: %target-run-simple-swift
2+
3+
// REQUIRES: executable_test
4+
// UNSUPPORTED: use_os_stdlib
5+
// UNSUPPORTED: back_deployment_runtime
6+
7+
import StdlibUnittest
8+
9+
var DeinitEscapeTestSuite = TestSuite("DeinitEscape")
10+
11+
var globalObjects: [AnyObject] = []
12+
13+
DeinitEscapeTestSuite.test("deinit escapes self") {
14+
expectCrashLater()
15+
16+
class C {
17+
deinit {
18+
globalObjects.append(self)
19+
}
20+
}
21+
_ = C()
22+
23+
expectUnreachable()
24+
}
25+
26+
runAllTests()

0 commit comments

Comments
 (0)