From 3aa1b9cdfacc5405b8649929369957836b3829a6 Mon Sep 17 00:00:00 2001 From: maruipu Date: Mon, 9 Nov 2020 23:53:42 +0800 Subject: [PATCH] Fix wrong strong layout result because of unaligned instance start. Inspired by: https://opensource.apple.com/source/objc4/objc4-756.2/runtime/objc-class.mm void _class_lookUpIvar() --- .../Layout/Classes/FBClassStrongLayout.mm | 3 ++- .../FBClassStrongLayoutTests.mm | 24 +++++++++++++++++++ 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/FBRetainCycleDetector/Layout/Classes/FBClassStrongLayout.mm b/FBRetainCycleDetector/Layout/Classes/FBClassStrongLayout.mm index a1feacf..f377021 100644 --- a/FBRetainCycleDetector/Layout/Classes/FBClassStrongLayout.mm +++ b/FBRetainCycleDetector/Layout/Classes/FBClassStrongLayout.mm @@ -146,7 +146,8 @@ static NSUInteger FBGetMinimumIvarIndex(__unsafe_unretained Class aCls) { if (count > 0) { Ivar ivar = ivars[0]; ptrdiff_t offset = ivar_getOffset(ivar); - minimumIndex = offset / (sizeof(void *)); + // unaligned bytes at the start of this class's ivars are not represented in the layout bitmap. + minimumIndex = (offset + (sizeof(void *) - 1)) / (sizeof(void *)); } free(ivars); diff --git a/FBRetainCycleDetectorTests/FBClassStrongLayoutTests.mm b/FBRetainCycleDetectorTests/FBClassStrongLayoutTests.mm index 07ac1d5..d2bbe6d 100644 --- a/FBRetainCycleDetectorTests/FBClassStrongLayoutTests.mm +++ b/FBRetainCycleDetectorTests/FBClassStrongLayoutTests.mm @@ -13,6 +13,7 @@ #import #import +#import @interface _RCDTestEmptyClass : NSObject @end @@ -157,6 +158,22 @@ @implementation _RCDTestClassWithCppStructAndStrongProperty } @end +@interface _RCDTestClassWithUnalignEndIvar : NSObject { + char content[20]; +} +@end +@implementation _RCDTestClassWithUnalignEndIvar +@end + +@interface _RCDTestClassWithUnalignEndIvarParentClass : _RCDTestClassWithUnalignEndIvar { + int integer; + __weak NSObject *object1; + NSObject *object2; +} +@end +@implementation _RCDTestClassWithUnalignEndIvarParentClass +@end + @interface FBClassStrongLayoutTests : XCTestCase @end @@ -260,4 +277,11 @@ - (void)testLayoutForClassWithCppStructAndStrongPropertyWillNotCrashAndFetchStro XCTAssertEqual([ivars count], 1); } +- (void)testLayoutForClassWithParentClassHasUnalignEndIvar +{ + NSArray> *ivars = FBGetObjectStrongReferences([_RCDTestClassWithUnalignEndIvarParentClass new], nil); + XCTAssertEqual([ivars count], 1); + XCTAssertEqualObjects([[ivars firstObject] namePath], @[@"object2"]); +} + @end