We analyzed it in our last articlealloc
Later, it was found that some details were not clearly explained. Here we will explore some places that we did not explore before.
This article will introduce the content for you:
1. Alloc content supplement
2. Memory alignment
3. Alignment exercises in the structure
4, some console printing tips
1. Alloc content supplement
1.1 review of the last article
We created a Person object in the OC Object Principle (part 1) and wrote the following code:
Person *p = [Person alloc];
Copy the code
When we explore the source code, we go to _objc_rootAlloc:
// Base class implementation of +alloc. cls is not nil.
// Calls [cls allocWithZone:nil].
id
_objc_rootAlloc(Class cls)
{
return callAlloc(cls, false/*checkNil*/, true/*allocWithZone*/);
}
Copy the code
This is our normal source code exploration process and there is nothing wrong with it.
1.2. Discovery of problems
Still a break point at this point:Using assembly code, I found a problem:Do you guys see what we’re about to enterobjc_alloc
, not_objc_rootAlloc
.
That’s weird, because it’s supposed to be _objc_rootAlloc.
1.3, continue to explore the source code
Since when debugging dynamically, the assembly code tells us that the first thing to enter isobjc_alloc
, then we will search in the source codeobjc_alloc
. (cmd + shift + O
)
So let’s break both objc_alloc and _objc_rootAlloc, and let’s see which one comes first. (Note that clean is used before testing to avoid cache impact)
One thing to note here is that both methods call callAlloc, but they take different arguments:
/******** _objc_rootAlloc ********/ id _objc_rootAlloc(Class cls) { return callAlloc(cls, false/*checkNil*/, true/*allocWithZone*/); } /******** objc_alloc ********/ // Calls [cls alloc]. id objc_alloc(Class cls) { return callAlloc(cls, true/*checkNil*/, false/*allocWithZone*/); } Copy the code
You can see that the first thing that goes in isobjc_alloc
. Write it down enter itcallAlloc
, set a breakpoint in this method:If you keep running, you’ll see that it skips everythingIf judgment
Go to the last line,objc_msgSend
:
Next comes the flow we explored in the underlying iOS exploration, OC Object Principles (part 1).
This is true when debugging dynamically; But the problem is, this process doesn’t work for what we’re trying to do, because alloc is _objc_rootAlloc, but when does it become objc_alloc?
My first impression of this was, did Apple swap methods somewhere? Or is itHOOK
?With this idea, the next is to look inside the source code. So I found this:
I followed it up and found it was_read_images
Inside call:So we’re right_read_images
Search, place breakpoints where it was called, run the project, and find something familiar:See? This isdyld
The load, that is, indyld
When it loads, the project is rightalloc
I’m going to make the substitutionIMP
Points to theobjc_alloc
; The execution of theobjc_alloc
After that, the message sending process is followedobjc_msgSend
. For those of you who are not familiar with this area, please refer to:IOS basic exploration — DyLD loading process IOS Infrastructure Exploration –Runtime (I) — Basics
To sum up, alloc will first go through a special process (objC_alloc), and then through the message sent into the ordinary alloc process.
The main reason for this is that alloc is an operation on memory, and Apple has some control over that operation.
2. Memory alignment
- Data member alignment rules:Structure (struct)(or combined (
union
), the first data member is placed inoffset
for0
Where later each data member is storedThe starting positionFrom you toThe size of the member (current member)
orSize of a member's child members
(As long as the member has child members, for exampleAn array of
.The structure of the body
, etc.)Integer timesStart. (such as:int
for4 bytes
, from4
An integer multiple of the address is stored. - The structure of the bodyAs a member: if oneThe structure of the bodyThere are certain things in itStructural member,Structural memberThe storage starts with an address that is an integer multiple of the size of the largest internal element. (such as:
struct a
Inside therestruct b
.b
There is achar
.int
.double
And so on, thenb
Should be from8
Integer multiples of start storage. - Finishing touches:The structure of the bodyThe total magnitude of omega, which is omega
sizeof
The result must be an integer multiple of the largest internal member, and the less must be made up.
C | OC | 32 – | A 64 – bit |
---|---|---|---|
bool | BOOL(64位) | 1 | 1 |
signed char | (__signed char)int8_t, BOOL(32 bits) | 1 | 1 |
unsigned char | Boolean | 1 | 1 |
short | Int16_t | 2 | 2 |
unsigned short | unichar | 2 | 2 |
int int32_t | NSInteger(32 bits), Boolean_T (32 bits) | 4 | 4 |
unsigned int | Boolean_t (64 bits), NSUInteger(32 bits) | 4 | 4 |
long | NSInteger(64位) | 4 | 8 |
unsigned long | NSUInteger(64位) | 4 | 8 |
long long | int64_t | 8 | 8 |
float | CGFloat(32位) | 4 | 4 |
double | CGFloat(64位) | 8 | 8 |
3. Alignment exercises in the structure
- Practice questions (1) :
struct JaxStruct1 {
double a; // 8 [0 7]
char b; // 1 [8]
int c; // 4 (9 10 11 [12 13 14 15]
short d; // 2 [16 17] 24
}struct1;
Copy the code
- Exercises (2) :
struct JaxStruct2 {
double a; // 8 [0 7]
int b; // 4 [8 9 10 11]
char c; // 1 [12]
short d; // 2 (13 [14 15] 16
}struct2;
Copy the code
- Exercises (3) :
struct JaxStruct3 {
double a; // 8 [0 7]
int b; // 4 [8 9 10 11]
char c; // 1 [12]
short d; // 2 (13 [14 15]
int e; // 4 [16 17 18 19]
struct JaxStruct1 str; // 24 (20 21 22 23 [sizeof(struct1)]
}struct3;
Copy the code
4, some console printing tips
When we use the console to print some data in Xcode, we use a form like this:
4.1. Print object memory data
x/nuf <address>
Copy the code
n
: indicates the number of memory units to be displayed.
u
: indicates the length of an address unit:b
: indicates a single byteh
: indicates two bytesw
: indicates four bytesg
: indicates eight bytes
f
: indicates the display mode. The value can be:x
: Displays variables in hexadecimal formatd
: Displays variables in decimal formatu
: Displays an unsigned integer in decimal formato
: Displays variables in octal formatt
: Displays variables in binary formata
: Displays variables in hexadecimal formati
: Instruction address formatc
: Displays variables in character formatf
: Displays variables in floating-point format
- Generally speaking, ellipsis
f
, the default ishexadecimal
:
4.2. Print object member variables
- If the member variable is
NSString
Or,Int
And so onpo
Execute to print:
$ po <address>
Copy the code
- If you want to print a floating point number, you can print it like this:
$e -f -- <address> $e -f -- <address>Copy the code