iOS-野指针

不错的博客:https://www.jianshu.com/p/33ee5e7d312c
最近在调研野指针的定位工具,对野指针有了更深入的理解,写篇文章总结下。

一、那什么是野指针?这是维基百科上的定义:

当所指向的对象被释放或者收回,但是对该指针没有作任何的修改,以至于该指针仍旧指向已经回收的内存地址,此情况下该指针便称迷途指针(即通常说的野指针)。

可以看出普通指针变成野指针需要满足两个条件:
1、其所指向的对象被释放或者收回,2、其本身没有做任何的修改。

   // ARC环境下:
    __unsafe_unretained UIView *testObj1 = [[UIView alloc] init];
   // testObj1 指向的内存区域已释放,本身未做任何修改,已成为野指针,向其发消息会闪退。

    __weak UIView *testObj2 = [[UIView alloc] init];
   // testObj2 指向的内存区域已释放,但本身被置为nil,不会成为野指针。

需要指出一点:访问野指针本身是没有问题的,不会引起异常;只有使用野指针时才会异常(比如OC里给对象发消息),表现就是闪退。

  // ARC环境下
    __unsafe_unretained UIView *testObj = [[UIView alloc] init];
    NSLog(@"testObj 指针指向的地址:%p 指针本身的地址:%p", testObj, &testObj);
    [testObj setNeedsLayout];
    // 可以看到NSlog打印不会闪退,调用[testObj setNeedsLayout];会闪退

二、什么情况下会产生野指针?

从产生过程上分析,有以下几种情况:
(1)指针变量未初始化:任何指针变量刚被创建时不会自动成为NULL指针,所以,指针变量在创建的同时应当被初始化,要么将指针设置为NULL,要么让它指向合法的内存。
(2)指针释放之后未置空:有时指针在dealloc或free后未赋值 NULL\nil,dealloc或free后它们只是把指针所指的内存给释放掉,但并没有把指针本身干掉。此时指针指向的就是“垃圾”内存。
释放后的指针应立即将指针置为NULL\nil,防止产生“野指针”。
(内存泄漏可能会导致野指针。

内存泄漏指程序在动态分配内存后没有及时释放,导致系统无法再次使用这些内存。如果指针变量指向的内存空间已经被释放,而指针变量没有被置为NULL或者被重新指向有效的内存地址,就会出现野指针。

举个例子,如果程序中使用malloc函数动态分配内存,但是在使用完后没有使用free函数释放内存,那么这块内存就会泄漏。如果指向这块已经泄漏的内存的指针没有被置为NULL或者被重新指向有效的内存地址,就可能出现野指针。因此,为了避免野指针问题,程序中应该注意及时释放已经动态分配的内存,避免内存泄漏问题)
(3)指针操作超越变量作用域:不要返回指向栈内存的指针或引用,因为栈内存在函数结束时会被释放。

第一点主要指使用C语言时。但是给初始化的指针赋个默认值是个好习惯,也是有必要的,不同的平台和编译环境对未初始化的指针的处理是有差异的。比如ARC环境下,定义NSInteger num,num 就可能被初始化成一个极大值。

下图是使用野指针可能出现的情况:

image

野指针的行为
使用野指针不一定百分百发生crash,这要看当时内存的使用情况,所以野指针的行为是多变不可预测的。野指针指向的地址空间在对象释放时被标记为空闲地址,接下来再去调用该野指针操作将有下列几种行为:

  • 该空间一直空闲,调用该属性会引发EXC_BAD_ACCESS;
  • 该空间被其他对象申请并占用,当调用该野指针的方法methodA时,这个空间上被分配的新对象并没有方法methodA, 会出现方法找不到:[xxx methodA] unrecognized selector sent to instance 0x1xxxxxxxx;
  • 该空间被其他对象申请并占用,当调用该野指针的方法methodA时,这个空间上被分配的新对象刚好也包含方法methodA, 调用之后不会出现任何crash;

作者:不上火喝纯净水
链接:https://www.jianshu.com/p/14e947dab4f9
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

三、怎么检测野指针?

Xcode已经提供了比较完善的检测方法,Malloc Scribble(内存涂鸦)和Zoombie Objects。也可以自己实现这两种检测方法。
1、实现Xcode的Malloc Scribble功能,Hook系统的free()函数,可以适用于c\c++类,标记每个要释放的对象:修改其指针指向的内存区域,在指针指向的内存区域填充数据(0x55), 使指针指向不可读的内存,再给这个对方发消息时,就会闪退。
!(ios hook框架之——fishhook)[https://www.jianshu.com/p/9e8236758462]

static void (*orig_free)(void *);
void safe_free(void* p){
    size_t memSiziee= malloc_size(p);
   // 给指针指向的内存区域填充值,指针本身没有发生改变
    memset(p, 0x55, memSiziee);
    orig_free(p);
    return;
}

int main(int argc, char * argv[]) {
    @autoreleasepool {
       // 使用fishhook库,替换系统的free(void *)函数实现
        rebind_symbols((struct rebinding[1]){{"free", safe_free, (void *)&orig_free}}, 1);
        return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
    }
}

2、实现Xcode的Zoombie Objects功能,实现自己的Zoombie Object(僵尸类),然后Hook系统的- (void)dealloc方法,只适用于oc类,修改对象的 isa 指针,令其指向特殊的僵尸类。僵尸类只有isa指针,没有任何方法实现,如果这个对象再次收到消息,就会闪退。

- (void)dealloc
{
   const char *className = object_getClassName(self);
   char *zombieClassName = NULL;
   do {
       Class zombieClass = objc_getClass(zombieClassName);

       objc_destructInstance(self); //关键

       object_setClass(self, zombieClass);

   } while (0);

   if (zombieClassName != NULL)
   {
       free(zombieClassName);
   }
}

这两种方法都是在产生野指针后,使用野指针时,让APP崩溃来发现是那里出的问题。也就是说需要尽量覆盖各种场景,才能发现野指针,并不能用扫描的方式提早发现。所以还是需要保证编码质量,从源头上避免出现野指针的问题。

作者:ch32053
链接:https://www.jianshu.com/p/8ad1c09aac72
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

内存涂鸦原理

Xcode的Malloc Scribble功能是一种用于内存调试的工具,它主要通过在已分配和释放的内存区域填充特定的数据模式,来帮助开发者更容易地发现和定位内存使用问题,特别是与野指针相关的问题。
Malloc Scribble的工作原理
分配时填充:当通过malloc(或类似函数)分配内存时,Malloc Scribble会在这些内存区域填充特定的数据(通常是0xAA)。这样做的好处是,如果分配的内存未被正确初始化就被使用,那么访问这些数据时很可能会立即触发错误,从而更容易被开发者发现。
释放后填充:当内存被释放后,Malloc Scribble会在这些内存区域填充另一种特定的数据(通常是0x55)。这样做的目的是,如果之后有野指针尝试访问这些已释放的内存,那么访问到的将是这些特定的数据,而不是随机数据,这有助于识别出野指针问题。
Malloc Scribble的作用
提高野指针的崩溃率:由于Malloc Scribble在释放内存后填充了特定的数据,这使得野指针访问这些内存时更容易触发崩溃,从而提高了野指针问题的可见性。
辅助内存调试:通过填充特定的数据,Malloc Scribble使得开发者在调试过程中更容易识别出内存使用的问题,如未初始化的内存使用、内存越界访问以及野指针等。
如何使用Malloc Scribble
在Xcode中,使用Malloc Scribble功能非常简单。只需在Xcode的scheme配置中,进入Diagnostics选项卡,然后勾选“Malloc Scribble”选项即可。此外,Xcode还提供了其他与内存调试相关的选项,如“Malloc Stack”、“Guard Malloc”和“Address Sanitizer”等,这些工具可以与Malloc Scribble一起使用,以提供更全面的内存调试能力。
注意事项
性能影响:虽然Malloc Scribble是一个非常有用的内存调试工具,但它会对应用程序的性能产生一定的影响。因此,在开发过程中应该谨慎使用,避免在性能敏感的环境下启用。
误报与漏报:虽然Malloc Scribble可以提高野指针问题的可见性,但它也可能产生误报或漏报。因此,在使用过程中需要结合其他调试手段进行综合分析。
总之,Xcode的Malloc Scribble功能是一个强大的内存调试工具,它可以帮助开发者更容易地发现和定位内存使用问题,特别是与野指针相关的问题。然而,在使用过程中也需要注意其性能影响和可能产生的误报或漏报问题。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,839评论 6 482
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,543评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 153,116评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,371评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,384评论 5 374
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,111评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,416评论 3 400
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,053评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,558评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,007评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,117评论 1 334
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,756评论 4 324
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,324评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,315评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,539评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,578评论 2 355
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,877评论 2 345

推荐阅读更多精彩内容

  • 一 野指针 C语言当我们声明1个指针变量,没有为这个指针变量赋初始值.这个指针变量的值是1个垃圾指 指向1块随机的...
    路飞_Luck阅读 3,140评论 5 10
  • iOS 底层原理 文章汇总[https://www.jianshu.com/p/412b20d9a0f6] 本文主...
    Style_月月阅读 3,287评论 0 17
  • 成因 野指针就是指向一个已删除的对象或者受限内存区域的指针。我们写C++的时候强调指针初始化为NULL,强调用完后...
    上官soyo阅读 20,838评论 4 80
  • 最近在调研野指针的定位工具,对野指针有了更深入的理解,写篇文章总结下。 一、那什么是野指针?这是维基百科上的定义:...
    ch32053阅读 5,321评论 0 4
  • 野指针就是指向一个已删除的对象或者受限内存区域的指针。我们写C++的时候强调指针初始化为NULL,强调用完后也为其...
    恋空K阅读 1,663评论 0 3