├── README.md └── iOS10NanoFreeCrashFixDemo ├── iOS10NanoFreeCrashFixDemo.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ └── xcuserdata │ │ └── chengjianfeng.xcuserdatad │ │ └── UserInterfaceState.xcuserstate └── xcuserdata │ └── chengjianfeng.xcuserdatad │ ├── xcdebugger │ └── Breakpoints_v2.xcbkptlist │ └── xcschemes │ ├── iOS10NanoFreeCrashFixDemo.xcscheme │ └── xcschememanagement.plist └── iOS10NanoFreeCrashFixDemo ├── AppDelegate.h ├── AppDelegate.m ├── Assets.xcassets └── AppIcon.appiconset │ └── Contents.json ├── Base.lproj ├── LaunchScreen.storyboard └── Main.storyboard ├── Info.plist ├── NanoFreeFix.m ├── ViewController.h ├── ViewController.mm └── main.m /README.md: -------------------------------------------------------------------------------- 1 | iOS10NanoFreeCrashFix 2 | ===================== 3 | 在iOS 10.0和10.1上,存在一个内存分配相关的系统bug,在nano_free时会产生崩溃,本文件可以帮助修复这个问题。
4 | 最早确定问题并提出解决方案的微信移动团队的公开文章:[iOS 10 Bug](https://mp.weixin.qq.com/s?__biz=MzAwNDY1ODY2OQ==&mid=2649286446&idx=1&sn=bc466e24751cfe553c59a8f786134034&chksm=8334c3acb4434abaf6aef0abd1f6891995699f47c4027c7ba2352849e04c98553136a2254a65&mpshare=1&scene=1&srcid=1226qEEY2uOFme8bcPWX89ru&key=564c3e9811aee0ab553a265111745d85cf3012b7d8cf0eb8b4c0811068a299a0cc254966186bcac2ea2378d24b71fe92d0cd96f11e0f59baf19c0204f26cbf3af52bad4e4f7d19426e7e533bf23b3578&ascene=0&uin=NTI1NDg2NTM1&devicetype=iMac+MacBookPro12%2C1+OSX+OSX+10.12.2+build(16C67)&version=12010110&nettype=WIFI&fontScale=100&pass_ticket=aR4V%2FjVncsqORZrS0KqIFvVcCJYVLUk5wFgDvgeuX4BYy%2FvgW0F2uyOkYgScyBs8). 5 | 6 | 7 | Nano_Free Crash的背景知识: 8 | ======================== 9 | * 当一个 iOS 应用启动后,此应用的所有内存分配申请,都会由一个或多个 zone 结构体来处理。
10 | * 在 iOS < 10.0 以及 iOS >= 10.2 的环境中,只存在一个这样的 zone。我们把它称作 Scalable Zone。
11 | * 在 iOS >= 10.0 以及 iOS < 10.2 的环境中,存在两个 Zone。分别是 Scalable Zone 和 Nano Zone。
12 | * 在 iOS >= 10.0 以及 iOS < 10.2 的环境中,Scalable Zone 和 Nano Zone 各有分工。Scalable Zone 负责处理大于 256 字节的内存分配申请,而 Nano Zone 负责处理小于等于 256 字节的内存分配申请。
13 | * 由 Scalable Zone 负责分配的内存,必须由 Scalable Zone 释放,不能由 Nano Zone 释放。反之亦然。
14 | * 每个 Zone 在释放一片内存前,会检查这片内存是不是由自己分配的。如果不是,则会在当前 stack 释放一个 Abort 信号。程序终止。
15 | * Nano Zone 用以下语句检查内存是否由自己分配:if(ptr>>28 == 0x17) {/*属于 Nano Zone*/}
16 | 17 | Nano_Free Crash的成因: 18 | ===================== 19 | * 在 iOS >= 10.0 以及 iOS < 10.2 的环境中,当 Scalable Zone 进行分配内存操作的次数超过了一个上限后,Scalable Zone 会分配出满足 if(ptr>>28 == 0x17) 条件的内存。当这片内存在未来某一时刻被释放时,会由 Nano Zone 接手,从而触发 Abort 信号,程序终止。
20 | 21 | 结合上述分析,我们不难得出以下推论: 22 | ================================ 23 | * FUP 发生的几率和程序的内存申请次数、内存占用总量、内存碎片化程度成正相关。
24 | * 也就是说,随着用户活跃度增加,发生 FUP 的可能性会上升。
25 | * FUP 发生时的调用栈没有参考意义。(Zone 错配发生在申请内存时,而非释放内存时。)
26 | 27 | 修复方案: 28 | ======== 29 | * 创建一个自己的zone命名为 guard zone。
30 | * 修改Nano zone的函数指针,重定向到guard zone:
31 | * 对于没有传入指针的函数,直接重定向到guard zone。
32 | * 对于有传入指针的函数,先用size判断所属的zone,再进行分发。
33 | 34 | 35 | 使用方法: 36 | ======== 37 | 将NanoFreeFix.m文件直接导入自己的工程即可。
38 | -------------------------------------------------------------------------------- /iOS10NanoFreeCrashFixDemo/iOS10NanoFreeCrashFixDemo.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 5F63E23C1E10E57F003C1B08 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 5F63E23B1E10E57F003C1B08 /* main.m */; }; 11 | 5F63E23F1E10E57F003C1B08 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 5F63E23E1E10E57F003C1B08 /* AppDelegate.m */; }; 12 | 5F63E2421E10E57F003C1B08 /* ViewController.mm in Sources */ = {isa = PBXBuildFile; fileRef = 5F63E2411E10E57F003C1B08 /* ViewController.mm */; }; 13 | 5F63E2451E10E57F003C1B08 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 5F63E2431E10E57F003C1B08 /* Main.storyboard */; }; 14 | 5F63E2471E10E580003C1B08 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 5F63E2461E10E580003C1B08 /* Assets.xcassets */; }; 15 | 5F63E24A1E10E580003C1B08 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 5F63E2481E10E580003C1B08 /* LaunchScreen.storyboard */; }; 16 | 5F63E2551E10E886003C1B08 /* NanoFreeFix.m in Sources */ = {isa = PBXBuildFile; fileRef = 5F63E2541E10E885003C1B08 /* NanoFreeFix.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; 17 | /* End PBXBuildFile section */ 18 | 19 | /* Begin PBXFileReference section */ 20 | 5F63E2371E10E57F003C1B08 /* iOS10NanoFreeCrashFixDemo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = iOS10NanoFreeCrashFixDemo.app; sourceTree = BUILT_PRODUCTS_DIR; }; 21 | 5F63E23B1E10E57F003C1B08 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 22 | 5F63E23D1E10E57F003C1B08 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 23 | 5F63E23E1E10E57F003C1B08 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 24 | 5F63E2401E10E57F003C1B08 /* ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = ""; }; 25 | 5F63E2411E10E57F003C1B08 /* ViewController.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = ViewController.mm; sourceTree = ""; }; 26 | 5F63E2441E10E57F003C1B08 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 27 | 5F63E2461E10E580003C1B08 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 28 | 5F63E2491E10E580003C1B08 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 29 | 5F63E24B1E10E580003C1B08 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 30 | 5F63E2521E10E5EA003C1B08 /* libc++abi.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = "libc++abi.tbd"; path = "usr/lib/libc++abi.tbd"; sourceTree = SDKROOT; }; 31 | 5F63E2541E10E885003C1B08 /* NanoFreeFix.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = NanoFreeFix.m; sourceTree = ""; }; 32 | /* End PBXFileReference section */ 33 | 34 | /* Begin PBXFrameworksBuildPhase section */ 35 | 5F63E2341E10E57F003C1B08 /* Frameworks */ = { 36 | isa = PBXFrameworksBuildPhase; 37 | buildActionMask = 2147483647; 38 | files = ( 39 | ); 40 | runOnlyForDeploymentPostprocessing = 0; 41 | }; 42 | /* End PBXFrameworksBuildPhase section */ 43 | 44 | /* Begin PBXGroup section */ 45 | 5F63E22E1E10E57F003C1B08 = { 46 | isa = PBXGroup; 47 | children = ( 48 | 5F63E2391E10E57F003C1B08 /* iOS10NanoFreeCrashFixDemo */, 49 | 5F63E2381E10E57F003C1B08 /* Products */, 50 | 5F63E2511E10E5EA003C1B08 /* Frameworks */, 51 | ); 52 | sourceTree = ""; 53 | }; 54 | 5F63E2381E10E57F003C1B08 /* Products */ = { 55 | isa = PBXGroup; 56 | children = ( 57 | 5F63E2371E10E57F003C1B08 /* iOS10NanoFreeCrashFixDemo.app */, 58 | ); 59 | name = Products; 60 | sourceTree = ""; 61 | }; 62 | 5F63E2391E10E57F003C1B08 /* iOS10NanoFreeCrashFixDemo */ = { 63 | isa = PBXGroup; 64 | children = ( 65 | 5F63E23D1E10E57F003C1B08 /* AppDelegate.h */, 66 | 5F63E23E1E10E57F003C1B08 /* AppDelegate.m */, 67 | 5F63E2401E10E57F003C1B08 /* ViewController.h */, 68 | 5F63E2411E10E57F003C1B08 /* ViewController.mm */, 69 | 5F63E2431E10E57F003C1B08 /* Main.storyboard */, 70 | 5F63E2461E10E580003C1B08 /* Assets.xcassets */, 71 | 5F63E2481E10E580003C1B08 /* LaunchScreen.storyboard */, 72 | 5F63E24B1E10E580003C1B08 /* Info.plist */, 73 | 5F63E23A1E10E57F003C1B08 /* Supporting Files */, 74 | 5F63E2541E10E885003C1B08 /* NanoFreeFix.m */, 75 | ); 76 | path = iOS10NanoFreeCrashFixDemo; 77 | sourceTree = ""; 78 | }; 79 | 5F63E23A1E10E57F003C1B08 /* Supporting Files */ = { 80 | isa = PBXGroup; 81 | children = ( 82 | 5F63E23B1E10E57F003C1B08 /* main.m */, 83 | ); 84 | name = "Supporting Files"; 85 | sourceTree = ""; 86 | }; 87 | 5F63E2511E10E5EA003C1B08 /* Frameworks */ = { 88 | isa = PBXGroup; 89 | children = ( 90 | 5F63E2521E10E5EA003C1B08 /* libc++abi.tbd */, 91 | ); 92 | name = Frameworks; 93 | sourceTree = ""; 94 | }; 95 | /* End PBXGroup section */ 96 | 97 | /* Begin PBXNativeTarget section */ 98 | 5F63E2361E10E57F003C1B08 /* iOS10NanoFreeCrashFixDemo */ = { 99 | isa = PBXNativeTarget; 100 | buildConfigurationList = 5F63E24E1E10E580003C1B08 /* Build configuration list for PBXNativeTarget "iOS10NanoFreeCrashFixDemo" */; 101 | buildPhases = ( 102 | 5F63E2331E10E57F003C1B08 /* Sources */, 103 | 5F63E2341E10E57F003C1B08 /* Frameworks */, 104 | 5F63E2351E10E57F003C1B08 /* Resources */, 105 | ); 106 | buildRules = ( 107 | ); 108 | dependencies = ( 109 | ); 110 | name = iOS10NanoFreeCrashFixDemo; 111 | productName = iOS10NanoFreeCrashFixDemo; 112 | productReference = 5F63E2371E10E57F003C1B08 /* iOS10NanoFreeCrashFixDemo.app */; 113 | productType = "com.apple.product-type.application"; 114 | }; 115 | /* End PBXNativeTarget section */ 116 | 117 | /* Begin PBXProject section */ 118 | 5F63E22F1E10E57F003C1B08 /* Project object */ = { 119 | isa = PBXProject; 120 | attributes = { 121 | LastUpgradeCheck = 0820; 122 | ORGANIZATIONNAME = ChengJianFeng; 123 | TargetAttributes = { 124 | 5F63E2361E10E57F003C1B08 = { 125 | CreatedOnToolsVersion = 8.2; 126 | DevelopmentTeam = 8529S722MZ; 127 | ProvisioningStyle = Automatic; 128 | }; 129 | }; 130 | }; 131 | buildConfigurationList = 5F63E2321E10E57F003C1B08 /* Build configuration list for PBXProject "iOS10NanoFreeCrashFixDemo" */; 132 | compatibilityVersion = "Xcode 3.2"; 133 | developmentRegion = English; 134 | hasScannedForEncodings = 0; 135 | knownRegions = ( 136 | en, 137 | Base, 138 | ); 139 | mainGroup = 5F63E22E1E10E57F003C1B08; 140 | productRefGroup = 5F63E2381E10E57F003C1B08 /* Products */; 141 | projectDirPath = ""; 142 | projectRoot = ""; 143 | targets = ( 144 | 5F63E2361E10E57F003C1B08 /* iOS10NanoFreeCrashFixDemo */, 145 | ); 146 | }; 147 | /* End PBXProject section */ 148 | 149 | /* Begin PBXResourcesBuildPhase section */ 150 | 5F63E2351E10E57F003C1B08 /* Resources */ = { 151 | isa = PBXResourcesBuildPhase; 152 | buildActionMask = 2147483647; 153 | files = ( 154 | 5F63E24A1E10E580003C1B08 /* LaunchScreen.storyboard in Resources */, 155 | 5F63E2471E10E580003C1B08 /* Assets.xcassets in Resources */, 156 | 5F63E2451E10E57F003C1B08 /* Main.storyboard in Resources */, 157 | ); 158 | runOnlyForDeploymentPostprocessing = 0; 159 | }; 160 | /* End PBXResourcesBuildPhase section */ 161 | 162 | /* Begin PBXSourcesBuildPhase section */ 163 | 5F63E2331E10E57F003C1B08 /* Sources */ = { 164 | isa = PBXSourcesBuildPhase; 165 | buildActionMask = 2147483647; 166 | files = ( 167 | 5F63E2421E10E57F003C1B08 /* ViewController.mm in Sources */, 168 | 5F63E2551E10E886003C1B08 /* NanoFreeFix.m in Sources */, 169 | 5F63E23F1E10E57F003C1B08 /* AppDelegate.m in Sources */, 170 | 5F63E23C1E10E57F003C1B08 /* main.m in Sources */, 171 | ); 172 | runOnlyForDeploymentPostprocessing = 0; 173 | }; 174 | /* End PBXSourcesBuildPhase section */ 175 | 176 | /* Begin PBXVariantGroup section */ 177 | 5F63E2431E10E57F003C1B08 /* Main.storyboard */ = { 178 | isa = PBXVariantGroup; 179 | children = ( 180 | 5F63E2441E10E57F003C1B08 /* Base */, 181 | ); 182 | name = Main.storyboard; 183 | sourceTree = ""; 184 | }; 185 | 5F63E2481E10E580003C1B08 /* LaunchScreen.storyboard */ = { 186 | isa = PBXVariantGroup; 187 | children = ( 188 | 5F63E2491E10E580003C1B08 /* Base */, 189 | ); 190 | name = LaunchScreen.storyboard; 191 | sourceTree = ""; 192 | }; 193 | /* End PBXVariantGroup section */ 194 | 195 | /* Begin XCBuildConfiguration section */ 196 | 5F63E24C1E10E580003C1B08 /* Debug */ = { 197 | isa = XCBuildConfiguration; 198 | buildSettings = { 199 | ALWAYS_SEARCH_USER_PATHS = NO; 200 | CLANG_ANALYZER_NONNULL = YES; 201 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 202 | CLANG_CXX_LIBRARY = "libc++"; 203 | CLANG_ENABLE_MODULES = YES; 204 | CLANG_ENABLE_OBJC_ARC = YES; 205 | CLANG_WARN_BOOL_CONVERSION = YES; 206 | CLANG_WARN_CONSTANT_CONVERSION = YES; 207 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 208 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 209 | CLANG_WARN_EMPTY_BODY = YES; 210 | CLANG_WARN_ENUM_CONVERSION = YES; 211 | CLANG_WARN_INFINITE_RECURSION = YES; 212 | CLANG_WARN_INT_CONVERSION = YES; 213 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 214 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 215 | CLANG_WARN_UNREACHABLE_CODE = YES; 216 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 217 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 218 | COPY_PHASE_STRIP = NO; 219 | DEBUG_INFORMATION_FORMAT = dwarf; 220 | ENABLE_STRICT_OBJC_MSGSEND = YES; 221 | ENABLE_TESTABILITY = YES; 222 | GCC_C_LANGUAGE_STANDARD = gnu99; 223 | GCC_DYNAMIC_NO_PIC = NO; 224 | GCC_NO_COMMON_BLOCKS = YES; 225 | GCC_OPTIMIZATION_LEVEL = 0; 226 | GCC_PREPROCESSOR_DEFINITIONS = ( 227 | "DEBUG=1", 228 | "$(inherited)", 229 | ); 230 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 231 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 232 | GCC_WARN_UNDECLARED_SELECTOR = YES; 233 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 234 | GCC_WARN_UNUSED_FUNCTION = YES; 235 | GCC_WARN_UNUSED_VARIABLE = YES; 236 | IPHONEOS_DEPLOYMENT_TARGET = 10.2; 237 | MTL_ENABLE_DEBUG_INFO = YES; 238 | ONLY_ACTIVE_ARCH = YES; 239 | SDKROOT = iphoneos; 240 | }; 241 | name = Debug; 242 | }; 243 | 5F63E24D1E10E580003C1B08 /* Release */ = { 244 | isa = XCBuildConfiguration; 245 | buildSettings = { 246 | ALWAYS_SEARCH_USER_PATHS = NO; 247 | CLANG_ANALYZER_NONNULL = YES; 248 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 249 | CLANG_CXX_LIBRARY = "libc++"; 250 | CLANG_ENABLE_MODULES = YES; 251 | CLANG_ENABLE_OBJC_ARC = YES; 252 | CLANG_WARN_BOOL_CONVERSION = YES; 253 | CLANG_WARN_CONSTANT_CONVERSION = YES; 254 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 255 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 256 | CLANG_WARN_EMPTY_BODY = YES; 257 | CLANG_WARN_ENUM_CONVERSION = YES; 258 | CLANG_WARN_INFINITE_RECURSION = YES; 259 | CLANG_WARN_INT_CONVERSION = YES; 260 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 261 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 262 | CLANG_WARN_UNREACHABLE_CODE = YES; 263 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 264 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 265 | COPY_PHASE_STRIP = NO; 266 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 267 | ENABLE_NS_ASSERTIONS = NO; 268 | ENABLE_STRICT_OBJC_MSGSEND = YES; 269 | GCC_C_LANGUAGE_STANDARD = gnu99; 270 | GCC_NO_COMMON_BLOCKS = YES; 271 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 272 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 273 | GCC_WARN_UNDECLARED_SELECTOR = YES; 274 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 275 | GCC_WARN_UNUSED_FUNCTION = YES; 276 | GCC_WARN_UNUSED_VARIABLE = YES; 277 | IPHONEOS_DEPLOYMENT_TARGET = 10.2; 278 | MTL_ENABLE_DEBUG_INFO = NO; 279 | SDKROOT = iphoneos; 280 | VALIDATE_PRODUCT = YES; 281 | }; 282 | name = Release; 283 | }; 284 | 5F63E24F1E10E580003C1B08 /* Debug */ = { 285 | isa = XCBuildConfiguration; 286 | buildSettings = { 287 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 288 | CLANG_WARN_SUSPICIOUS_MOVE = NO; 289 | DEVELOPMENT_TEAM = 8529S722MZ; 290 | INFOPLIST_FILE = iOS10NanoFreeCrashFixDemo/Info.plist; 291 | IPHONEOS_DEPLOYMENT_TARGET = 10.0; 292 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 293 | PRODUCT_BUNDLE_IDENTIFIER = CJF.iOS10NanoFreeCrashFixDemo; 294 | PRODUCT_NAME = "$(TARGET_NAME)"; 295 | }; 296 | name = Debug; 297 | }; 298 | 5F63E2501E10E580003C1B08 /* Release */ = { 299 | isa = XCBuildConfiguration; 300 | buildSettings = { 301 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 302 | CLANG_WARN_SUSPICIOUS_MOVE = NO; 303 | DEVELOPMENT_TEAM = 8529S722MZ; 304 | INFOPLIST_FILE = iOS10NanoFreeCrashFixDemo/Info.plist; 305 | IPHONEOS_DEPLOYMENT_TARGET = 10.0; 306 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 307 | PRODUCT_BUNDLE_IDENTIFIER = CJF.iOS10NanoFreeCrashFixDemo; 308 | PRODUCT_NAME = "$(TARGET_NAME)"; 309 | }; 310 | name = Release; 311 | }; 312 | /* End XCBuildConfiguration section */ 313 | 314 | /* Begin XCConfigurationList section */ 315 | 5F63E2321E10E57F003C1B08 /* Build configuration list for PBXProject "iOS10NanoFreeCrashFixDemo" */ = { 316 | isa = XCConfigurationList; 317 | buildConfigurations = ( 318 | 5F63E24C1E10E580003C1B08 /* Debug */, 319 | 5F63E24D1E10E580003C1B08 /* Release */, 320 | ); 321 | defaultConfigurationIsVisible = 0; 322 | defaultConfigurationName = Release; 323 | }; 324 | 5F63E24E1E10E580003C1B08 /* Build configuration list for PBXNativeTarget "iOS10NanoFreeCrashFixDemo" */ = { 325 | isa = XCConfigurationList; 326 | buildConfigurations = ( 327 | 5F63E24F1E10E580003C1B08 /* Debug */, 328 | 5F63E2501E10E580003C1B08 /* Release */, 329 | ); 330 | defaultConfigurationIsVisible = 0; 331 | defaultConfigurationName = Release; 332 | }; 333 | /* End XCConfigurationList section */ 334 | }; 335 | rootObject = 5F63E22F1E10E57F003C1B08 /* Project object */; 336 | } 337 | -------------------------------------------------------------------------------- /iOS10NanoFreeCrashFixDemo/iOS10NanoFreeCrashFixDemo.xcodeproj/project.xcworkspace/xcuserdata/chengjianfeng.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TreasureU/iOS10NanoFreeCrashFix/fa48ca43e0e8b376244dd67e7e2e3a4ec167cafe/iOS10NanoFreeCrashFixDemo/iOS10NanoFreeCrashFixDemo.xcodeproj/project.xcworkspace/xcuserdata/chengjianfeng.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /iOS10NanoFreeCrashFixDemo/iOS10NanoFreeCrashFixDemo.xcodeproj/xcuserdata/chengjianfeng.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | -------------------------------------------------------------------------------- /iOS10NanoFreeCrashFixDemo/iOS10NanoFreeCrashFixDemo.xcodeproj/xcuserdata/chengjianfeng.xcuserdatad/xcschemes/iOS10NanoFreeCrashFixDemo.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 39 | 40 | 41 | 42 | 43 | 44 | 54 | 56 | 62 | 63 | 64 | 65 | 66 | 67 | 73 | 75 | 81 | 82 | 83 | 84 | 86 | 87 | 90 | 91 | 92 | -------------------------------------------------------------------------------- /iOS10NanoFreeCrashFixDemo/iOS10NanoFreeCrashFixDemo.xcodeproj/xcuserdata/chengjianfeng.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | iOS10NanoFreeCrashFixDemo.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | 5F63E2361E10E57F003C1B08 16 | 17 | primary 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /iOS10NanoFreeCrashFixDemo/iOS10NanoFreeCrashFixDemo/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // iOS10NanoFreeCrashFixDemo 4 | // 5 | // Created by ChengJianFeng on 2016/12/26. 6 | // Copyright © 2016年 ChengJianFeng. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface AppDelegate : UIResponder 12 | 13 | @property (strong, nonatomic) UIWindow *window; 14 | 15 | 16 | @end 17 | 18 | -------------------------------------------------------------------------------- /iOS10NanoFreeCrashFixDemo/iOS10NanoFreeCrashFixDemo/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // iOS10NanoFreeCrashFixDemo 4 | // 5 | // Created by ChengJianFeng on 2016/12/26. 6 | // Copyright © 2016年 ChengJianFeng. All rights reserved. 7 | // 8 | 9 | #import "AppDelegate.h" 10 | 11 | @interface AppDelegate () 12 | 13 | @end 14 | 15 | @implementation AppDelegate 16 | 17 | 18 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 19 | // Override point for customization after application launch. 20 | return YES; 21 | } 22 | 23 | 24 | - (void)applicationWillResignActive:(UIApplication *)application { 25 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 26 | // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game. 27 | } 28 | 29 | 30 | - (void)applicationDidEnterBackground:(UIApplication *)application { 31 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 32 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 33 | } 34 | 35 | 36 | - (void)applicationWillEnterForeground:(UIApplication *)application { 37 | // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background. 38 | } 39 | 40 | 41 | - (void)applicationDidBecomeActive:(UIApplication *)application { 42 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 43 | } 44 | 45 | 46 | - (void)applicationWillTerminate:(UIApplication *)application { 47 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 48 | } 49 | 50 | 51 | @end 52 | -------------------------------------------------------------------------------- /iOS10NanoFreeCrashFixDemo/iOS10NanoFreeCrashFixDemo/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "29x29", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "29x29", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "40x40", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "40x40", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "60x60", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "60x60", 31 | "scale" : "3x" 32 | } 33 | ], 34 | "info" : { 35 | "version" : 1, 36 | "author" : "xcode" 37 | } 38 | } -------------------------------------------------------------------------------- /iOS10NanoFreeCrashFixDemo/iOS10NanoFreeCrashFixDemo/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /iOS10NanoFreeCrashFixDemo/iOS10NanoFreeCrashFixDemo/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /iOS10NanoFreeCrashFixDemo/iOS10NanoFreeCrashFixDemo/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | LSRequiresIPhoneOS 22 | 23 | UILaunchStoryboardName 24 | LaunchScreen 25 | UIMainStoryboardFile 26 | Main 27 | UIRequiredDeviceCapabilities 28 | 29 | armv7 30 | 31 | UISupportedInterfaceOrientations 32 | 33 | UIInterfaceOrientationPortrait 34 | UIInterfaceOrientationLandscapeLeft 35 | UIInterfaceOrientationLandscapeRight 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /iOS10NanoFreeCrashFixDemo/iOS10NanoFreeCrashFixDemo/NanoFreeFix.m: -------------------------------------------------------------------------------- 1 | // 2 | // NanoFreeFix.m 3 | // iOS10NanoFreeCrashFixDemo 4 | // 5 | // Created by ChengJianFeng on 2016/12/26. 6 | // Copyright © 2016年 ChengJianFeng. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | #import 12 | #include 13 | #include 14 | #import 15 | 16 | malloc_zone_t* NanoCrashGuardInitialize(); 17 | static malloc_zone_t*s_default_zone = NULL; 18 | static malloc_zone_t*s_guard_zone = NULL; 19 | typedef void *(*GuardMalloc) (struct _malloc_zone_t*zone, size_t size); 20 | typedef void (*GuardFree) (struct _malloc_zone_t*zone, void*prt); 21 | typedef size_t (*GuardSize)(struct _malloc_zone_t*zone, const void*prt); 22 | GuardMalloc s_default_zone_origin_malloc = NULL; 23 | GuardFree s_default_zone_origin_free = NULL; 24 | GuardSize s_default_zone_origin_size = NULL; 25 | 26 | typedef void *(*GuardRealloc) (struct _malloc_zone_t*zone, void * ptr, size_t size); 27 | GuardRealloc s_default_zone_origin_realloc = NULL; 28 | void *default_zone_realloc(struct _malloc_zone_t*zone, void * ptr, size_t size) 29 | { 30 | size_t s = s_guard_zone->size(s_guard_zone,ptr); 31 | if(s){ 32 | return malloc_zone_realloc(s_guard_zone, ptr, size); 33 | } 34 | return s_default_zone_origin_realloc(zone, ptr, size); 35 | } 36 | 37 | typedef void *(*GuardCalloc) (struct _malloc_zone_t*zone, size_t num_items, size_t size); 38 | GuardCalloc s_default_zone_origin_calloc = NULL; 39 | void *default_zone_calloc(struct _malloc_zone_t*zone, size_t num_items, size_t size) 40 | { 41 | return malloc_zone_calloc(s_guard_zone, num_items, size); 42 | } 43 | 44 | typedef void *(*GuardValloc) (struct _malloc_zone_t*zone, size_t size); 45 | GuardValloc s_default_zone_origin_valloc = NULL; 46 | void *default_zone_valloc(struct _malloc_zone_t*zone, size_t size) 47 | { 48 | return malloc_zone_valloc(s_guard_zone, size); 49 | } 50 | 51 | void*default_zone_malloc(struct _malloc_zone_t*zone, size_t size) 52 | { 53 | return malloc_zone_malloc(s_guard_zone, size); 54 | } 55 | void default_zone_free(struct _malloc_zone_t*zone, void*ptr) 56 | { 57 | size_t s = s_guard_zone->size(s_guard_zone,ptr); 58 | if(s){ 59 | return malloc_zone_free(s_guard_zone, ptr); 60 | } 61 | return s_default_zone_origin_free(zone, ptr); 62 | } 63 | size_t default_zone_size(struct _malloc_zone_t *zone, const void*ptr) 64 | { 65 | size_t s = s_guard_zone->size(s_guard_zone, ptr); 66 | if(s)return s; 67 | return s_default_zone_origin_size(zone, ptr); 68 | } 69 | 70 | malloc_zone_t*NanoCrashGuardInitialize() 71 | { 72 | malloc_zone_t * tmp_s_guard_zone = malloc_create_zone(getpagesize(), 0); 73 | malloc_set_zone_name(tmp_s_guard_zone, "GuardZone"); 74 | s_default_zone = malloc_default_zone(); 75 | mprotect(s_default_zone, sizeof(malloc_zone_t),PROT_READ | PROT_WRITE); 76 | OSMemoryBarrier(); 77 | OSAtomicCompareAndSwapPtr((void*)s_default_zone_origin_malloc,(void*)s_default_zone->malloc,(void*volatile)&s_default_zone_origin_malloc); 78 | OSAtomicCompareAndSwapPtr((void*)s_default_zone_origin_free,(void*)s_default_zone->free,(void*volatile)&s_default_zone_origin_free); 79 | OSAtomicCompareAndSwapPtr((void*)s_default_zone_origin_size,(void*)s_default_zone->size,(void*volatile)&s_default_zone_origin_size); 80 | OSAtomicCompareAndSwapPtr((void*)s_default_zone->malloc,(void*)default_zone_malloc,(void*volatile)&s_default_zone->malloc); 81 | OSAtomicCompareAndSwapPtr((void*)s_default_zone->free,(void*)default_zone_free,(void*volatile)&s_default_zone->free); 82 | OSAtomicCompareAndSwapPtr((void*)s_default_zone->size,(void*)default_zone_size,(void*volatile)&s_default_zone->size); 83 | 84 | OSAtomicCompareAndSwapPtr((void*)s_default_zone_origin_realloc,(void*)s_default_zone->realloc,(void*volatile)&s_default_zone_origin_realloc); 85 | OSAtomicCompareAndSwapPtr((void*)s_default_zone->realloc,(void*)default_zone_realloc,(void*volatile)&s_default_zone->realloc); 86 | 87 | OSAtomicCompareAndSwapPtr((void*)s_default_zone_origin_calloc,(void*)s_default_zone->calloc,(void*volatile)&s_default_zone_origin_calloc); 88 | OSAtomicCompareAndSwapPtr((void*)s_default_zone->calloc,(void*)default_zone_calloc,(void*volatile)&s_default_zone->calloc); 89 | 90 | OSAtomicCompareAndSwapPtr((void*)s_default_zone_origin_valloc,(void*)s_default_zone->valloc,(void*volatile)&s_default_zone_origin_valloc); 91 | OSAtomicCompareAndSwapPtr((void*)s_default_zone->valloc,(void*)default_zone_valloc,(void*volatile)&s_default_zone->valloc); 92 | 93 | OSMemoryBarrier(); 94 | mprotect(s_default_zone, sizeof(malloc_zone_t), PROT_READ); 95 | return tmp_s_guard_zone; 96 | } 97 | 98 | static BOOL needFix() { 99 | NSString *version = [[UIDevice currentDevice] systemVersion]; 100 | if (NO ==[version respondsToSelector:@selector(containsString:)]) { 101 | return NO; 102 | } 103 | //只有这两个小版本需要修复,其他版本不用。iOS 10.2上已经修复这个问题,虽然realloc依然有问题,但是可以继续观察。 104 | if( [version hasPrefix:@"10.0"] || [version hasPrefix:@"10.1"] ){ 105 | NSLog(@"Now version is %@,需要修复",version); 106 | return YES; 107 | }else { 108 | NSLog(@"Now version is %@,不需要修复",version); 109 | return NO; 110 | } 111 | } 112 | 113 | __attribute__((constructor)) static void JDSHFupFix(void) { 114 | @autoreleasepool { 115 | if (needFix()) { 116 | NSLog(@"Nano Free bug 修复代码生效"); 117 | s_guard_zone = NanoCrashGuardInitialize(); 118 | } 119 | } 120 | } 121 | -------------------------------------------------------------------------------- /iOS10NanoFreeCrashFixDemo/iOS10NanoFreeCrashFixDemo/ViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.h 3 | // iOS10NanoFreeCrashFixDemo 4 | // 5 | // Created by ChengJianFeng on 2016/12/26. 6 | // Copyright © 2016年 ChengJianFeng. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface ViewController : UIViewController 12 | 13 | 14 | @end 15 | 16 | -------------------------------------------------------------------------------- /iOS10NanoFreeCrashFixDemo/iOS10NanoFreeCrashFixDemo/ViewController.mm: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.m 3 | // iOS10NanoFreeCrashFixDemo 4 | // 5 | // Created by ChengJianFeng on 2016/12/26. 6 | // Copyright © 2016年 ChengJianFeng. All rights reserved. 7 | // 8 | 9 | #import "ViewController.h" 10 | #import 11 | 12 | @interface ViewController () 13 | 14 | @end 15 | 16 | @implementation ViewController 17 | { 18 | std::vectorptrs; 19 | } 20 | 21 | 22 | - (void)viewDidLoad { 23 | [super viewDidLoad]; 24 | // Do any additional setup after loading the view, typically from a nib. 25 | #define NANO_MAX (256) 26 | while(1){ 27 | uintptr_t ptr= (uintptr_t)malloc(NANO_MAX+1); 28 | ptrs.push_back(ptr); 29 | if(ptr>>28 == 0x17) 30 | { 31 | break; 32 | } 33 | } 34 | #undef NANO_MAX 35 | } 36 | 37 | 38 | - (void)didReceiveMemoryWarning { 39 | [super didReceiveMemoryWarning]; 40 | // Dispose of any resources that can be recreated. 41 | } 42 | 43 | 44 | @end 45 | -------------------------------------------------------------------------------- /iOS10NanoFreeCrashFixDemo/iOS10NanoFreeCrashFixDemo/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // iOS10NanoFreeCrashFixDemo 4 | // 5 | // Created by ChengJianFeng on 2016/12/26. 6 | // Copyright © 2016年 ChengJianFeng. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "AppDelegate.h" 11 | 12 | int main(int argc, char * argv[]) { 13 | @autoreleasepool { 14 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 15 | } 16 | } 17 | --------------------------------------------------------------------------------