NSString内容擦除相关

作者: ncnocure | 来源:发表于2017-01-04 17:29 被阅读80次

测试结论

  1. 常量字符串在正式赋值之前就存在,会保留到整个程序运行期间,无法清除。
  2. 在调用函数结束的时候NSString字符串才会自动清空,之前都能在内存中搜到。
  3. 非常量字符串可以通过念茜的CFStringGetCStringPtr的方式清空。(念茜方法详情
    只想了解怎么清除NSString的朋友看到这里就够了,下面是以上结论的测试过程。

引子

最近手头的iOS项目对安全性要求非常高。
某个敏感数据使用NSString存储,非常敏感,必须即用即清理。NSString对象会通过ARC自动释放,而并没有显式的清除方法,所以并不能确定自动释放之后内容是否自动清除。
找到念茜博主提供的NSString字符串清除。
为了验证方法有效性,我直接使用念茜的代码试验

_text = @"12dfavkasie";  
memset((__bridge voidvoid *)(_text), 0, _text.length - 1);  
NSString *myString = [[NSString alloc]initWithFormat:@"information"];  
NSLog(@"Origal text : %@ \n",myString);  //断点1

“Origal text :”没有显示字符串内容,但是在断点1进行内存扫描依然能搜到一个12dfavkasie。所以为了验证该方法有效性,需要解决如下几个问题。

  1. 断点1搜到的字符串是常量字符串还是NSString没擦除的结果。
  2. NSString是否在最后一次调用的时候自动擦除。
  3. 使用非常量字符串来排除常量字符串干扰,使用这种方法依然能够清除就能证明该方法可以有效清除NSString。

首先建立可以进行内存扫描的iOS环境。

iOS扫描内存过程

  1. 使用盘古越狱将手头iPhone 4s iOS 7.1.2 越狱。
  2. 在Cydia上下载OpenSSH。
  3. 在Cydia上添加源:http://grantdouglas.co.uk 下载 memscan。
  4. 在MAC上使用SSH连接OpenSSH。
    ssh root@192.168.2.199
    iPhone手机默认密码为 :alpine
    RA手机,修改为:Rongan1234
  5. 运行iOS中间件工具。
  6. 用工具名字, 获取iOS工具PID如下:
    ps-ax | grep SignTool
    ps-ax | grep Mgr
  7. 获取的PID对应进程的内存。
    memscan -p 64685 -d -o out4.bin
  8. 搜索获取内存中的数据
    grep -c 12345677 out4.bin
    得到数据为0,则内存中找不到该字符串。
    得到数据不为0,使用grep -a查看该字符串出现的具体位置。

测试过程

编写用于测试的程序验证如下三个问题:

  1. 断点1搜到的字符串是常量字符串还是NSString没擦除的结果。
    通过程序1确定常量字符串的特性。
  2. NSString是否在最后一次调用的时候自动擦除。
    建立两个NSString,确定两个字符串清除的时间。
  3. 使用非常量字符串来排除常量字符串干扰,使用这种方法依然能够清除就能证明该方法可以有效清除NSString。

常量字符串是否一直存在?

    NSString *testStr = [[NSString alloc] initWithFormat:@"14642334"];
    NSString *testStr1 = [[NSString alloc] initWithFormat:@"sdfsafd"];
    NSString *testStr2 = [[NSString alloc] initWithFormat:@"dsfdsafd"];
    NSString *testStr3 = [[NSString alloc] initWithFormat:@"dncmviwmaf"];
    
    NSLog(@"test1");
    NSLog(@"test2");
    NSLog(@"test1");
    NSLog(@"test2");
    [testStr compare:testStr1];
    [testStr compare:testStr2];
    [testStr compare:testStr3];

在该段代码运行之前,用memscan获取内存,用grep -C 10 14642334 获取该字符串附近的上下文,结果如下。

lengthOfBytesUsingEncoding:
getCString:maxLength:encoding:
keyEnumerator
nextObject
test
14642334
sdfsafd
dsfdsafd
dncmviwmaf
test1
test2

当该函数运行结束之后,查找14642334,结果一样。

结论

常量字符串特点如下:

  1. 集中存储在一个位置。
  2. 无论代码有没有运行到常量字符串所在位置,内存中都会包含这个字符串的内容。
    所以之前念茜代码最后搜到的测试字符串应该是常量字符串。

NSString是否自动清除

测试代码:

    unsigned char testByteStr[10];//断点0
    testByteStr[0] = '1';//14642334
    testByteStr[1] = '4';
    testByteStr[2] = '6';
    testByteStr[3] = '4';
    testByteStr[4] = '2';
    testByteStr[5] = '3';
    testByteStr[6] = '3';
    testByteStr[7] = '4';
    NSString *testStr = [[NSString alloc] initWithBytes:testByteStr length:8 encoding:NSASCIIStringEncoding];
    testByteStr[0] = '4';//47951438
    testByteStr[1] = '7';
    testByteStr[2] = '9';
    testByteStr[3] = '5';
    testByteStr[4] = '1';
    testByteStr[5] = '4';
    testByteStr[6] = '3';
    testByteStr[7] = '8';
    NSString *testStr2 =[[NSString alloc] initWithBytes:testByteStr length:8 encoding:NSASCIIStringEncoding];
    memset(testByteStr, 0, 8);
    NSLog(@"test");//断点1
    [testStr compare:testStr2];
    NSLog(@"test");//断点2
    NSLog(@"%l",testStr.length);
    NSLog(@"test");//断点3
    testStr = @"123";
    NSLog(@"test");//断点4

结果和分析:
断点0时,14642334出现0次,47951438出现0次。
断点1时,14642334出现1次,47951438出现1次。
testByteStr已经用memset清空,所以内存中唯一的14642334是testStr。唯一的47951438是testStr2。
断点2时,14642334出现1次,47951438出现1次。
之后testStr2最后一次调用在断点2前,然而testStr2依然能搜到。所以NSString并没有在最后一次调用时自我清除。
断点3时,14642334出现1次,47951438出现1次。
断点4时,14642334出现1次,47951438出现1次。
断点5为该函数执行结束之后的断点,14642334出现0次,47951438出现0次。

结论

NSString只会在所在函数段结束的时候自动清空。

排除常量字符串干扰,擦除字符串

    unsigned char testByteStr[10];//断点0
    testByteStr[0] = '1';//14642334
    testByteStr[1] = '4';
    testByteStr[2] = '6';
    testByteStr[3] = '4';
    testByteStr[4] = '2';
    testByteStr[5] = '3';
    testByteStr[6] = '3';
    testByteStr[7] = '4';
    NSString *testStr = [[NSString alloc] initWithBytes:testByteStr length:8 encoding:NSASCIIStringEncoding];
    memset(testByteStr , 0 , 8);
    char *str = malloc(9*sizeof(char));//断点1
    str = (char *)CFStringGetCStringPtr((CFStringRef)testStr,CFStringGetSystemEncoding());
    NSLog(@"test");//断点2
    memset(str , 0 , 7);
    NSLog(@"test");//断点3

在Xcode里运行测试程序,在程序运行到断点0,1,2,3的时候使用memscan扫描14642334的数量。
断点0结果:0
断点1结果:1
testByteStr已经清空。内存中唯一14642334是testStr。
断点2结果:1
执行CFStringGetCStringPtr之后,内存中依然只有一个14642334。而之前已经试验过testStr字符串在函数结束之后才会清空,所以str指向testStr存储14642334的内存位置。
断点3结果:0
清空str之后,testStr也清空了。

结论

念茜的方法可以有效清空NSString。

测试结论

  1. 常量字符串在正式赋值之前就存在,会保留到整个程序运行期间,无法清除。
  2. 在调用函数结束的时候NSString字符串才会自动清空,之前都能在内存中搜到。
  3. 非常量字符串可以通过CFStringGetCStringPtr的方式清空。

相关文章

  • NSString内容擦除相关

    测试结论 常量字符串在正式赋值之前就存在,会保留到整个程序运行期间,无法清除。 在调用函数结束的时候NSStrin...

  • NSString相关

    1.NSString如何计算字符串长度 文档中很明确的表示了 其实 NSString 是个UTF-16的数组。他的...

  • NSString相关

    目录[-]1.常用功能使用1)初始化2)截取3)分解4)查找5)替换6)路径相关7)字符串是否为空8)字符串比较9...

  • NSString相关使用

    字符串的创建 通过不同的方式创建字符串,字符串对象存储的位置也不一样如果通过字符串常量创建,那么字符串对象存储在常...

  • NSString相关处理

    --实例化方法-------------- NSString *str = [[NSString alloc] i...

  • oc NSString相关

    标签:ios开发入门

  • iOS - 数据类型转换

    NSString 转 NSData NSData 转 NSString Struct转NSData 时间转换相关 ...

  • iOS开发陷阱之NSString -compare

    iOS开发陷阱之NSString - compare NSString有多个compare相关方法: -(NSCo...

  • copy for Swift

    1.非集合 NSString (1)NSString copy:内容拷贝 不可变类型 ...

  • 手机号.邮箱.身份证等相关正则表达式

    主要是对NSString的扩展验证相关 ///////////////////////////// 正则表达式相关...

网友评论

    本文标题:NSString内容擦除相关

    本文链接:https://www.haomeiwen.com/subject/umukvttx.html