我的应用程序存在内存增长问题。
自 在这里描述完整的代码是令人生畏的, 我将其缩小到这个简单的场景,我在两个 View Controller 之间来回切换以学习基本的内存动态。
- (void)viewDidLoad {
[super viewDidLoad];
for (int i=0; i<100000; i++)
{
__weak NSString* str = [NSString stringWithFormat:@"abcsdf"];
str = nil;
}
}
这应该不会显示内存增长,因为我分配了“str”并通过使“str”变为零来释放“str”,从而失去了所有者。
但是,内存不断增长。 每次我加载这个 View Controller 时,内存都会不断增长并且永远不会恢复。
谁能告诉我这是为什么? 我正在使用 ARC。
最佳答案
您的代码片段包含一些关于 iOS/OS X 内存管理的有趣内容。
__weak NSString* str = [NSString stringWithFormat:@"abcsdf"];
str = nil;
代码和下面一样,没有ARC。
NSString* str = [[[NSString alloc] initWithFormat:@"abcsdf"] autorelease];
str = nil;
因为 stringWithFormat: 类方法不以“alloc”、“new”、“copy”或“mutableCopy”开头。这是命名规则。因此 NSString 对象由自动释放池保留。 Autorelease Pool 可能在主 Runloop 中。因此 NSString 对象没有立即释放。它会导致内存增长。 @autoreleasepool 解决了它。
@autoreleasepool {
__weak NSString* str = [NSString stringWithFormat:@"abcsdf"];
str = nil;
}
NSString 对象在 @autoreleasepool 代码块的末尾被释放。
顺便说一句,[NSString stringWithFormat:@"abcsdf"] 可能不会每次都分配任何内存。原因是它是静态字符串。让我们用这个类做进一步的解释。
#import <Foundation/Foundation.h>
@interface Test : NSObject
+ (instancetype)test;
@end
@implementation Test
- (void)dealloc {
NSLog(@"Test dealloc");
}
+ (instancetype)test
{
return [[Test alloc] init];
}
@end
这是__weak的测试代码。
@autoreleasepool {
NSLog(@"BEGIN: a = [Test test]\n");
__weak Test *a = [Test test];
NSLog(@"END: a = [Test test]\n");
a = nil;
NSLog(@"DONE: a = nil\n");
}
代码的结果。
BEGIN: a = [Test test]
END: a = [Test test]
DONE: a = nil
Test dealloc
你说过 通过使 'str' 变为 nil 来解除分配 'str',从而失去所有者。这是不正确的。 a 弱变量没有对象的所有权。 Autorelease Pool 确实拥有该对象的所有权。这就是为什么该对象在 @autoreleasepool 代码块末尾被释放的原因。看看这个案例的其他测试代码。
NSLog(@"BEGIN: a = [[Test alloc] init]\n");
__weak Test *a = [[Test alloc] init];
NSLog(@"END: a = [[Test alloc] init]\n");
a = nil;
NSLog(@"DONE: a = nil\n");
从代码中可以看到编译警告。
warning: assigning retained object to weak variable; object will be
released after assignment [-Warc-unsafe-retained-assign]
__weak Test *a = [[Test alloc] init];
^ ~~~~~~~~~~~~~~~~~~~
[[Test alloc] init] 没有将对象注册到自动释放池。好吧,不再需要 @autoreleasepool 了。而 a 是 __weak 变量,所以该对象不会被任何东西保留。因此结果是
BEGIN: a = [[Test alloc] init]
Test dealloc
END: a = [[Test alloc] init]
DONE: a = nil
没有所有权就没有生命。该对象在分配后立即被释放。我认为您想编写没有 __weak 的代码,如下所示。
NSLog(@"BEGIN: a = [[Test alloc] init]\n");
Test *a = [[Test alloc] init];
NSLog(@"END: a = [[Test alloc] init]\n");
a = nil;
NSLog(@"DONE: a = nil\n");
结果符合预期。通过将 nil 分配给强变量 a 来释放该对象。然后没有人拥有该对象的所有权,该对象被释放。
BEGIN: a = [[Test alloc] init]
END: a = [[Test alloc] init]
Test dealloc
DONE: a = nil
关于ios - 内存增长之谜(Objective-C),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31176061/
作为我的Rails应用程序的一部分,我编写了一个小导入程序,它从我们的LDAP系统中吸取数据并将其塞入一个用户表中。不幸的是,与LDAP相关的代码在遍历我们的32K用户时泄漏了大量内存,我一直无法弄清楚如何解决这个问题。这个问题似乎在某种程度上与LDAP库有关,因为当我删除对LDAP内容的调用时,内存使用情况会很好地稳定下来。此外,不断增加的对象是Net::BER::BerIdentifiedString和Net::BER::BerIdentifiedArray,它们都是LDAP库的一部分。当我运行导入时,内存使用量最终达到超过1GB的峰值。如果问题存在,我需要找到一些方法来更正我的代
这里有一个很好的答案解释了如何在Ruby中下载文件而不将其加载到内存中:https://stackoverflow.com/a/29743394/4852737require'open-uri'download=open('http://example.com/image.png')IO.copy_stream(download,'~/image.png')我如何验证下载文件的IO.copy_stream调用是否真的成功——这意味着下载的文件与我打算下载的文件完全相同,而不是下载一半的损坏文件?documentation说IO.copy_stream返回它复制的字节数,但是当我还没有下
ruby如何管理内存。例如:如果我们在执行过程中采用C程序,则以下是内存模型。类似于这个ruby如何处理内存。C:__________________|||stack|||------------------||||------------------|||||Heap|||||__________________|||data|__________________|text|__________________Ruby:? 最佳答案 Ruby中没有“内存”这样的东西。Class#allocate分配一个对象并返回该对象。这就是程序
我正在尝试解析一个文本文件,该文件每行包含可变数量的单词和数字,如下所示:foo4.500bar3.001.33foobar如何读取由空格而不是换行符分隔的文件?有什么方法可以设置File("file.txt").foreach方法以使用空格而不是换行符作为分隔符? 最佳答案 接受的答案将slurp文件,这可能是大文本文件的问题。更好的解决方案是IO.foreach.它是惯用的,将按字符流式传输文件:File.foreach(filename,""){|string|putsstring}包含“thisisanexample”结果的
1.错误信息:Errorresponsefromdaemon:Gethttps://registry-1.docker.io/v2/:net/http:requestcanceledwhilewaitingforconnection(Client.Timeoutexceededwhileawaitingheaders)或者:Errorresponsefromdaemon:Gethttps://registry-1.docker.io/v2/:net/http:TLShandshaketimeout2.报错原因:docker使用的镜像网址默认为国外,下载容易超时,需要修改成国内镜像地址(首先阿里
我正在尝试为我的iOS应用程序设置cocoapods但是当我执行命令时:sudogemupdate--system我收到错误消息:当前已安装最新版本。中止。当我进入cocoapods的下一步时:sudogeminstallcocoapods我在MacOS10.8.5上遇到错误:ERROR:Errorinstallingcocoapods:cocoapods-trunkrequiresRubyversion>=2.0.0.我在MacOS10.9.4上尝试了同样的操作,但出现错误:ERROR:Couldnotfindavalidgem'cocoapods'(>=0),hereiswhy:U
你好,我无法成功如何在散列中删除key后释放内存。当我从哈希中删除键时,内存不会释放,也不会在手动调用GC.start后释放。当从Hash中删除键并且这些对象在某处泄漏时,这是预期的行为还是GC不释放内存?如何在Ruby中删除Hash中的键并在内存中取消分配它?例子:irb(main):001:0>`ps-orss=-p#{Process.pid}`.to_i=>4748irb(main):002:0>a={}=>{}irb(main):003:0>1000000.times{|i|a[i]="test#{i}"}=>1000000irb(main):004:0>`ps-orss=-p
print"Enteryourpassword:"pass=STDIN.noecho(&:gets)puts"Yourpasswordis#{pass}!"输出:Enteryourpassword:input.rb:2:in`':undefinedmethod`noecho'for#>(NoMethodError) 最佳答案 一开始require'io/console'后来的Ruby1.9.3 关于ruby-为什么不能使用类IO的实例方法noecho?,我们在StackOverflow上
这会导致Ruby出现内存问题吗?我知道如果大小超过10KB,Open-URI会写入TempFile。但是HTTParty会在写入TempFile之前尝试将整个PDF保存到内存吗?src=Tempfile.new("file.pdf")src.binmodesrc.writeHTTParty.get("large_file.pdf").parsed_response 最佳答案 您可以使用Net::HTTP。参见thedocumentation(特别是标题为“流媒体响应机构”的部分)。这是文档中的示例:uri=URI('http://e
在部署在heroku上的Rails应用程序(v:3.1)中,我在内存中获得了更多具有相同ID的对象。我的heroku控制台日志:>>Project.find_all_by_id(92).size=>2>>ActiveRecord::Base.connection.execute('select*fromprojectswhereid=92').to_a.size=>1这怎么可能?可能是什么问题? 最佳答案 解决方案根据您的SQL查询,您的数据库中显然没有重复条目。也许您的类项目中的size或length方法已被覆盖。我试过find_