This article takes a look at the malloc source code with a small example

First we create a person class with several properties, and then print sizeof (), class_getInstanceSize(), and malloc_size().

Person *person = [Person alloc];
person.name      = @"ErBao";
person.nickName  = @"EB";

NSLog(@"sizeof(persion): %lu", **sizeof**(person)); 
NSLog(@"class_getInstanceSize([Person class]): %lu", class_getInstanceSize([Person class]));
NSLog(@"malloc_size((__bridge const void *)(person)): %lu", malloc_size((__bridge const void *)(person)));

Copy the code

The printed result is:

  • sizeof(persion): 8
  • class_getInstanceSize([LGPerson class]): 40
  • malloc_size((__bridge const void *)(person)): 48

Resolution:

  • The person in sizeof(person) is a pointer, and a pointer takes 8 bytes, so sizeof(person) is 8
  • Class_getInstanceSize uses 8-byte alignment. The following figure shows the byte size of the class instance and the memory size of each attribute8 + 8 + 4 + 8 = 28, plus the ISA pointer8After the bytes for36According to the memory alignment principle, the total size must be an integer multiple of the longest attribute size, so the result is40

Malloc_size ((__bridge const void *)(person)) = 48

  • mallocThe source code forlibMallocLibrary, we first download good source codeOpensource.apple.com/tarballs/li…

Void *p = calloc(1, 40); void *p = calloc(1, 40); Click calloc to call the following source code:

Then we go to the _malloc_zone_calloc method.

Click on itcallocOnly declarations, not function calls. At this point we’re doing it in the consolepo zone->calloc

We then find the implementation based on the output

You can see thatdefault_zone_callocThere it goes againzone->callocAnd then Po again.

findnano_callocmethods

_nano_malloc_check_clearGuess the size of the possible open memory point to view (method is a bit long, screenshot may not see clearly, I will directly paste the code snippet):

**static** **void** * _nano_malloc_check_clear(nanozone_t *nanozone, size_t size, boolean_t cleared_requested) { MALLOC_TRACE(TRACE_nano_malloc, (uintptr_t)nanozone, size, cleared_requested, 0); void *ptr; size_t slot_key; size_t slot_bytes = segregated_size_to_fit(nanozone, size, &slot_key); // Note slot_key is set here mag_index_t mag_index = nano_mag_index(nanozone); nano_meta_admin_t pMeta = &(nanozone->meta_data[mag_index][slot_key]); ptr = OSAtomicDequeue(&(pMeta->slot_LIFO), offsetof(**struct** chained_block_s, next)); if (ptr) { unsigned debug_flags = nanozone->debug_flags; #if NANO_FREE_DEQUEUE_DILIGENCE size_t gotSize; nano_blk_addr_t p; // the compiler holds this in a register p.addr = (uint64_t)ptr; // Begin the dissection of ptr if (NANOZONE_SIGNATURE ! = p.fields.nano_signature) { malloc_zone_error(debug_flags, true, "Invalid signature for pointer %p dequeued from free list\n", ptr); } if (mag_index ! = p.fields.nano_mag_index) { malloc_zone_error(debug_flags, true, "Mismatched magazine for pointer %p dequeued from free list\n", ptr); } gotSize = _nano_vet_and_size_of_free(nanozone, ptr); if (0 == gotSize) { malloc_zone_error(debug_flags, true, "Invalid pointer %p dequeued from free list\n", ptr); } if (gotSize ! = slot_bytes) { malloc_zone_error(debug_flags, true, "Mismatched size for pointer %p dequeued from free list\n", ptr); } if (! _nano_block_has_canary_value(nanozone, ptr)) { malloc_zone_error(debug_flags, true, "Heap corruption detected, free list canary is damaged for %p\n", "*** Incorrect guard value: %lu\n", ptr ((chained_block_t)ptr)->double_free_guard); } #if defined(DEBUG) void *next = (void *)(((chained_block_t)ptr)->next); if (next) { p.addr = (uint64_t)next; // Begin the dissection of next if (NANOZONE_SIGNATURE ! = p.fields.nano_signature) { malloc_zone_error(debug_flags, true, "Invalid next signature for pointer %p dequeued from free " "list, next = %p\n", ptr, "next"); } if (mag_index ! = p.fields.nano_mag_index) { malloc_zone_error(debug_flags, true, "Mismatched next magazine for pointer %p dequeued from " "free list, next = %p\n", ptr, next); } gotSize = _nano_vet_and_size_of_free(nanozone, next); if (0 == gotSize) { malloc_zone_error(debug_flags, true, "Invalid next for pointer %p dequeued from free list", "next = %p\n", ptr, next); } if (gotSize ! = slot_bytes) { malloc_zone_error(debug_flags, true, "Mismatched next size for pointer %p dequeued from free, "list, next = %p\n", ptr, next); } } #endif /* DEBUG */ #endif /* NANO_FREE_DEQUEUE_DILIGENCE */ ((chained_block_t)ptr)->double_free_guard = 0; ((chained_block_t)ptr)->next = **NULL**; // clear out next pointer to protect free list } else { ptr = segregated_next_block(nanozone, pMeta, slot_bytes, mag_index); } if (cleared_requested && ptr) { memset(ptr, 0, slot_bytes); // **TODO: Needs a memory barrier after memset to ensure zeroes land first? ** } return ptr; }Copy the code

PTR = OSAtomicDequeue(&(pMeta->slot_LIFO), offsetof(**struct** chained_block_s, next)); We see that LIFO speculates first and then out, so PTR is on the stack, assigning the heap memory address to Ptr.segregated_next_block underneath is the do while loop, which looks for the addressable address in memory

#define SHIFT_NANO_QUANTUM 4. Insegregated_size_to_fitFour to the right, then four to the left. 16 – byte alignment. So the abovemalloc_size(person)for48

To sum up:

  • inThe heapThe amount of memory opened up is justobjectMemory to16Byte alignment
  • The object’sMember variablesThat isStructural interiorIn order to8Byte alignment
  • Objects and objects are in memory16Byte alignment

Why are objects aligned with 16 bytes? Let’s analyze it briefly:

First the conclusion:

8Bytes have a higher probability of error. The object is stored in memory as follows:Any object must contain at least one 8-byteisaAnd then you have to allocate space to your member variables, even if they take up space2So the space that this object ends up taking up is zero8(ISA)+2(member variable)+4(alignment) = 16 bytes.At least one object must occupy16Bytes, if read with8A group of bytes is read, so the number of calculations is increased, and the probability of errors is increased. Then why not?32Bit alignment? Because this often leads to a waste of space.

The appended drawings

Size of memory occupied by base data types:

Reference:

Juejin. Cn/post / 697159…