4 objc\[\d+\]: Deallocator object 0x[0-9a-fA-F]+ overreleased while already deallocating; break on objc_overrelease_during_dealloc_error to debug
7 no overrelease enforcement
17 @interface Deallocator : TestRoot @end
18 @implementation Deallocator
26 testprintf("Retain a lot during dealloc\n");
29 testassert([o retainCount] == rc);
32 if (rc % 0x100000 == 0) testprintf("%zx/%zx ++\n", rc, LOTS);
33 } while (++rc < LOTS);
35 testassert([o retainCount] == rc);
39 if (rc % 0x100000 == 0) testprintf("%zx/%zx --\n", rc, LOTS);
43 testassert([o retainCount] == rc);
46 testprintf("Overrelease during dealloc\n");
48 // Not all architectures enforce this.
49 #if !SUPPORT_NONPOINTER_ISA
50 testwarn("no overrelease enforcement");
51 fprintf(stderr, "no overrelease enforcement\n");
60 size_t clz(uintptr_t isa) {
61 if (sizeof(uintptr_t) == 4)
62 return __builtin_clzl(isa);
63 testassert(sizeof(uintptr_t) == 8);
64 return __builtin_clzll(isa);
69 Deallocator *o = [Deallocator new];
74 uintptr_t isa = *(uintptr_t *)o;
76 // Assume refcount in high bits.
77 LOTS = 1 << (4 + clz(isa));
78 testprintf("LOTS %zu via cntlzw\n", LOTS);
81 testprintf("LOTS %zu via guess\n", LOTS);
87 testprintf("Retain a lot\n");
90 testassert([o retainCount] == rc);
93 if (rc % 0x100000 == 0) testprintf("%zx/%zx ++\n", rc, LOTS);
94 } while (++rc < LOTS);
96 testassert([o retainCount] == rc);
100 if (rc % 0x100000 == 0) testprintf("%zx/%zx --\n", rc, LOTS);
104 testassert([o retainCount] == rc);
107 testprintf("tryRetain a lot\n");
110 objc_storeWeak(&w, o);
114 testassert([o retainCount] == rc);
116 objc_loadWeakRetained(&w);
117 if (rc % 0x100000 == 0) testprintf("%zx/%zx ++\n", rc, LOTS);
118 } while (++rc < LOTS);
120 testassert([o retainCount] == rc);
124 if (rc % 0x100000 == 0) testprintf("%zx/%zx --\n", rc, LOTS);
128 testassert([o retainCount] == rc);
130 testprintf("dealloc\n");
132 testassert(TestRootDealloc == 0);
133 testassert(w != nil);
135 testassert(TestRootDealloc == 1);
136 testassert(w == nil);