To prepare

  • To get to the bottom of it, you need to use Clang to compile OC classes into the underlying C/C++

  • Clang is a LLVM-based C/C++/ object-C compiler that acts as a front end to LLVM

  • Compile the target main.h file into a c++ file

clang -rewrite-objc main.m -o main.cpp  
Copy the code
  • UIKit error:Note the SDK version
Clang-rewrite-objc-fobjc-arc-fobjc-runtime =ios-13.0.0 -isysroot / Applications/Xcode. App/Contents/Developer/Platforms/iPhoneSimulator platform/Developer/SDKs/iPhoneSimulator13.0. The SDK main.mCopy the code
  • xcrunCommand inclangOn the basis of some encapsulation, to better use some
Xcrun - SDK iphonesimulator clang -arch arm64 -rewrite-objc main.m -o main-arm64.cppCopy the code
Xcrun - SDK iphoneOS clang -arch arm64 - rerewrite -objc main.m -o mainarm64.cppCopy the code

The nature and extension of objects

What is an object

  • withxcrun -sdk iphonesimulator clang -arch arm64 -rewrite-objc WLWPerson.m -o WLWLPerson.cppwillWLWPerson.mCompile the generatedWLWPerson.cpp

  • Open theWLWPerson.cppFound that the code was very long and difficult to read. We can search according to their familiar class positioning, retrievalWLWPerson

  • It can be seen thatWLWPersonThe actual isobjc_object.The nature of the object isobjc_objectThe structure of the body

  • classtypeobjc_class* ClassIs a pointer to a structure

  • idalsoobjc_object *Pointer, so useidDo not need to add*

  • Generate the correspondingThe set, the getMethod, where we can see hidden argumentsself

  • This is the correspondinggetMethod, we found that the value is passedselfThe memory translation value, which also indicates the memory arrangement of objects, the first one isisa, and the member variables are arranged one at a time

Combination field

struct WLWCar1 {
    BOOL front; / / 0 to 1
    BOOL back;
    BOOL left;
    BOOL right;
};

struct WLWCar2 {
    BOOL front: 1;
    BOOL back : 1;
    BOOL left : 1;
    BOOL right: 1;
};

/ / coexistence
struct WLWTeacher1 {
    char        *name;
    int         age;
    double      height ;
};

// union: member variables are mutually exclusive, shared memory
union WLWTeacher2 {
    char        *name;
    int         age;
    double      height ;
};
Copy the code
  • WLWCar1There are 4 internal onesbool, to take up4Bytes, which is just32Bits, to avoid waste, we can write it as a byte, a byte8Bits, we’re going to use one for each bitbool
  • WLWCar2One byte, binary representation0000, 1111,.:The following indicates how many digits are occupied
  • Structures are co-existing, and all member variables can be assigned at the same time
  • Unions are different. Assignments between member variables are mutually exclusive, meaning that only one of them has a value, such as an assignmentnameAnd then the assignmentage, thennameThey don’t have any value, because they all share a piece of memory, and the last one assigned will give the previous one to the replacement segment
  • Union saves memory space

NonpointerIsa analysis

  • objectisaInitialization of, as can be seenisaisisa_ttype

  • isa_tIs a union, the member variables are mutually exclusive
  • defined(ISA_BITFIELD)Macro, whether definedISA_BITFIELD, the review found that the definitions vary from architecture to architecture, but are generally similar
// __has_feature(ptrauth_calls) only has arm64E above A12
#   if __has_feature(ptrauth_calls) || TARGET_OS_SIMULATOR
#     define ISA_MASK        0x007ffffffffffff8ULL // Get the mask of CLS
#     define ISA_MAGIC_MASK  0x0000000000000001ULL // Get the mask of MAGIC
#     define ISA_MAGIC_VALUE 0x0000000000000001ULL
#     define ISA_HAS_CXX_DTOR_BIT 0
#     define ISA_BITFIELD                                                      \
        uintptr_t nonpointer        : 1;    // Nonpointer \ uintptr_t has_assoc: 1; // mark optimize ISA pointer \ uintptr_t weakly_referenced: 1; Uintptr_t shiftcls_and_sig: 32; // Uintptr_t has_sidetable_rc: 1; Uintptr_t extra_rc: 8 // Store the result of subtracting the value of the reference count of this object
#     define RC_ONE   (1ULL<<56)
#     define RC_HALF  (1ULL<<7)
#   else
#     define ISA_MASK        0x0000000ffffffff8ULL
#     define ISA_MAGIC_MASK  0x000003f000000001ULL
#     define ISA_MAGIC_VALUE 0x000001a000000001ULL
#     define ISA_HAS_CXX_DTOR_BIT 1
#     define ISA_BITFIELD                                                      \
        uintptr_t nonpointer        : 1;   // Nonpointer \ uintptr_t has_assoc: 1; // uintptr_t has_cxx_dtor: 1; Uintptr_t shiftcls: 33; // Uintptr_t shiftcls: 33; // class /*MACH_VM_MAX_ADDRESS 0x1000000000*/ \ uintptr_t magic: 6; // Uintptr_t Weakly_referenced: 1; // Uintptr_t unused: 1; // Whether is being released \ uintptr_t has_sidetable_rc: 1; // as above \ uintptr_t extra_rc: 19
#     define RC_ONE   (1ULL<<45)
#     define RC_HALF  (1ULL<<18)
#   endif

# elif __x86_64__
#   define ISA_MASK        0x00007ffffffffff8ULL
#   define ISA_MAGIC_MASK  0x001f800000000001ULL
#   define ISA_MAGIC_VALUE 0x001d800000000001ULL
#   define ISA_HAS_CXX_DTOR_BIT 1
#   define ISA_BITFIELD                                                        \
      uintptr_t nonpointer        : 1;                                         \
      uintptr_t has_assoc         : 1;                                         \
      uintptr_t has_cxx_dtor      : 1;                                         \
      uintptr_t shiftcls          : 44; /*MACH_VM_MAX_ADDRESS 0x7fffffe00000*/ \
      uintptr_t magic             : 6;                                         \
      uintptr_t weakly_referenced : 1;                                         \
      uintptr_t unused            : 1;                                         \
      uintptr_t has_sidetable_rc  : 1;                                         \
      uintptr_t extra_rc          : 8
Copy the code
  • To avoid wasting memory, we can see thatisaPointer if yesnonapointerIsa.64Bits hold a lot more than just a pointer

Isa derived Class

First, an object P1 is initialized and a breakpoint is set. Then LLDB is used for debugging

  • We already know the arrangement inside the object, the first variable is oursisa
  • We also know thatisaisisa_tUnion, internal store class, whether weak reference, reference counting and so on
  • And then we seeISA_MASK 0x007ffffffffffff8ULLMask, we’re throughisaWith the upper mask to get oursshiftClsIs the class
  • A mask, for example, is a mask that, when put on, reveals what you want
  • You can also see objects by printingsiaMiddle class address, that’s usWLWPersonClass address of the
  • initIsaIs theisaAssignment of a bit field
  • If it is notnonapointerIsa.isaDeposit isclassThe address of the