swift_slowAlloc Crash 分析

一、Crash詳情

Crash類型

exception EXC_BREAKPOINT (SIGTRAP)
reason EXC_BREAKPOINT EXC_ARM_BREAKPOINT fault_address:0x0000000185ba6824

Crash堆棧

0 libswiftCore.dylib 0x0000000185ba6824 swift_slowAlloc.cold.1 (in libswiftCore.dylib) + 16
1 libswiftCore.dylib 0x0000000185b2c9d8 _swift_slowAlloc (in libswiftCore.dylib) + 208
2 libswiftCore.dylib 0x0000000185b2cb48 _swift_allocObject (in libswiftCore.dylib) + 60
3 libswiftCore.dylib 0x0000000185abe67c specialized static _DictionaryStorage.resize(original: __RawDictionaryStorage, capacity: Int, move: Bool) (in libswiftCore.dylib) + 328
4 libswiftCore.dylib 0x000000018591fbf8 _NativeDictionary._copyOrMoveAndResize(capacity: Int, moveElements: Bool) (in libswiftCore.dylib) + 324
5 libswiftCore.dylib 0x0000000185920034 _NativeDictionary.ensureUnique(isUnique: Bool, capacity: Int) (in libswiftCore.dylib) + 52

二、分析過程

經過排查, 該對象不存在多線程訪問的問題

通過 異常類型 EXC_BREAKPOINT, 猜測是Swift Runtime中的異常觸發, 參考SwiftAlloc的源代碼

// When alignMask == ~(size_t(0)), allocation uses the "default"
// _swift_MinAllocationAlignment. This is different than calling swift_slowAlloc
// with `alignMask == _swift_MinAllocationAlignment - 1` because it forces
// the use of AlignedAlloc. This allows manually allocated to memory to always
// be deallocated with AlignedFree without knowledge of its original allocation
// alignment.
//
// For alignMask > (_minAllocationAlignment-1)
// i.e. alignment == 0 || alignment > _minAllocationAlignment:
//   The runtime must use AlignedAlloc, and the standard library must
//   deallocate using an alignment that meets the same condition.
//
// For alignMask <= (_minAllocationAlignment-1)
// i.e. 0 < alignment <= _minAllocationAlignment:
//   The runtime may use either malloc or AlignedAlloc, and the standard library
//   must deallocate using an identical alignment.
void *swift::swift_slowAlloc(size_t size, size_t alignMask) {
  void *p;
  // This check also forces "default" alignment to use AlignedAlloc.
  if (alignMask <= MALLOC_ALIGN_MASK) {
#if defined(__APPLE__) && SWIFT_STDLIB_HAS_DARWIN_LIBMALLOC
    p = malloc_zone_malloc(DEFAULT_ZONE(), size);
#else
    p = malloc(size);
#endif
  } else {
    size_t alignment = (alignMask == ~(size_t(0)))
                           ? _swift_MinAllocationAlignment
                           : alignMask + 1;
    p = AlignedAlloc(size, alignment);
  }
  if (!p) swift::crash("Could not allocate memory.");
  return p;
}

 

關於 EXC_BREAKPOINT

The breakpoint exception type indicates a trace trap interrupted the process. A trace trap gives an attached debugger the chance to interrupt the process at a specific point in its execution. On ARM processors, this appears as EXC_BREAKPOINT (SIGTRAP). On x86_64 processors, this appears as EXC_BAD_INSTRUCTION (SIGILL).

The Swift runtime uses trace traps for specific types of unrecoverable errors—see Addressing Crashes from Swift Runtime Errors for information on those errors. Some lower-level libraries, such as Dispatch, trap the process with this exception upon encountering an unrecoverable error, and log additional information about the error in the Additional Diagnostic Information section of the crash report. See Diagnostic Messages for information about those messages.

If you want to use the same technique in your own code for unrecoverable errors, call the __builtin_trap() function. This allows the system to generate a crash report with thread backtraces that show how you reached the unrecoverable error.

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章