我正在将 githubt 上的 NSData+Base64 opensrc 库用于下个月到期的项目。我刚刚开始分析、分析和优化,并发现了来自该代码的泄漏。我已经禁用了 NSZombie 和所有调试方法和 try-catch,因为我之前发现它们有时会泄漏内存。精确定位泄漏的确切线是:
- (NSString *)base64EncodedString
{
return [self base64EncodedStringWithWrapWidth:0];
}
和拆卸:
+0x0 pushl %ebp
+0x1 movl %esp, %ebp
+0x3 subl $24, %esp
+0x6 calll -[NSData(Base64) base64EncodedString]+0xb
+0xb popl %eax
+0xc movl +86389(%eax), %eax
+0x12 movl %eax, +4(%esp)
+0x16 movl +8(%ebp), %eax
+0x19 movl %eax, (%esp)
+0x1c movl $0, +8(%esp)
+0x24 calll DYLD-STUB$$objc_msgSend // 100% leak
+0x29 addl $24, %esp
+0x2c popl %ebp
+0x2d ret
我没有联系作者,因为我担心没有正确使用库可能是我的错,或者只是我的代码的其他部分。
当我使用特定方法(仅使用一次)时,我会在加密例程之后这样做:
+ (NSString *) encryptString:(NSString *)plaintext withKey:(NSString *)key
{
// Convert string-to-be-encrypted to Data
NSData *inData = [Miscellaneous utf8string2data:plaintext];
// Encrypt, Encode, Return
return [[self encryptData:inData withKey:key] base64EncodedString];
}
但是,我感觉内存泄漏的实际点在方法调用的方法中
base64EncodedStringWithWrapWidth
确切的行是:
outputBytes = realloc(outputBytes, outputLength);
NSString *result = [[NSString alloc] initWithBytesNoCopy:outputBytes length:outputLength encoding:NSASCIIStringEncoding freeWhenDone:YES];
所以我想我的问题是:1)有没有人使用这个库观察到类似的行为 2)我是否可能通过使用分配不当的字符串来引发泄漏 3)任何人都知道如何解决它,或者我可以用另一个库来替换它?
谢谢!
编辑:我已将 Instruments 指出为泄漏代码的上述行更改为:
outputBytes = realloc(outputBytes, outputLength);
NSString *result = [[NSString alloc] initWithBytes:outputBytes length:outputLength encoding:NSASCIIStringEncoding];
free(outputBytes);
但是,我仍然从那条线上泄漏。目标 C 中的 malloc/realloc/free 是否存在问题?
编辑2:
Bytes Used # Leaks Symbol Name
512 Bytes 5.2% 2 thread_start
512 Bytes 5.2% 2 _pthread_start
512 Bytes 5.2% 2 __NSThread__main__
512 Bytes 5.2% 2 -[NSThread main]
512 Bytes 5.2% 2 -[Sync get]
512 Bytes 5.2% 2 -[Request DoRequest]
512 Bytes 5.2% 2 -[Request encryptMessage:]
512 Bytes 5.2% 2 +[AES256 encryptString:withKey:]
512 Bytes 5.2% 2 -[NSData(Base64) base64EncodedString]
512 Bytes 5.2% 2 -[NSData(Base64) base64EncodedStringWithWrapWidth:]
512 Bytes 5.2% 2 -[NSPlaceholderString initWithBytes:length:encoding:]
512 Bytes 5.2% 2 CFStringCreateWithBytes
512 Bytes 5.2% 2 __CFStringCreateImmutableFunnel3
512 Bytes 5.2% 2 _CFRuntimeCreateInstance
512 Bytes 5.2% 2 CFAllocatorAllocate
512 Bytes 5.2% 2 __CFAllocatorSystemAllocate
我不知道它是否有助于确定这是否是错误警告,但是通过不过滤任何内容,罪魁祸首似乎是 CFAllocatorSystemAllocate:
+0x13 calll DYLD-STUB$$malloc_zone_malloc
+0x18 addl $8, %esp
所以我开始对这是否真的是泄漏有所保留。但是,在模拟器和 iPad 上进行调试具有相同的结果。使用了 ARC,我试图复制对象而不是引用它们。
解决方案:我发现了泄漏,它是在使用错误类型的演员不正确地实施的方法中(愚蠢的我,我第一次没有看到这个)
return (__bridge_transfer NSString *)CFURLCreateStringByAddingPercentEscapes(NULL,
(__bridge_retained CFStringRef)string,
NULL,
(CFStringRef)@"!*'\"();:@&=+$,/?%#[]% ",
CFStringConvertNSStringEncodingToEncoding(encoding));
bridge_retain 在这里将 ARC 增加了 1,因此它没有被释放,这就是我收到警告的原因。有趣的是,在我意识到出了什么问题之前,这是我查看的最后一段代码。谢谢您的帮助