是什么导致 "Virtual Memory exhausted" 错误?
What causes a "Virtual Memory exhausted" error?
好吧..事情是这样的..我正在构建一个应用程序,当用户点击下载按钮时,它会下载一堆图像(准确地说是 296)。
在模拟器中一切正常,在我的 iPhone (4S) 上大约第 100 张图像上它崩溃并出现错误:
malloc: * mach_vm_map(size= "some random number") failed (error code= 3)* error: can't allocate region
libBacktraceRecording.dylib: allocate_free_list_pages() -- virtual memory exhausted!
这是我为下载这些图片而编写的代码:
-(void)getData
{
NSError *error;
int i;
NSArray *brojLinije = [[NSArray alloc] initWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"linije" ofType:@"plist"]];
NSArray *urlSlike = [[NSArray alloc] initWithContentsOfFile:[[NSBundle mainBundle]pathForResource:@"urlSlike" ofType:@"plist"]];
NSArray *pocetno = [[NSArray alloc] initWithContentsOfFile:[[NSBundle mainBundle]pathForResource:@"pocetno" ofType:@"plist"]];
NSArray *sortiranje = [[NSArray alloc] initWithContentsOfFile:[[NSBundle mainBundle]pathForResource:@"sort" ofType:@"plist"]];
NSArray*paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *desktopDir = [paths firstObject];
UIImage *image1 = [[UIImage alloc] init];
for (i = 0; i<296; i++) {
NSString *brojLinije1 = [NSString stringWithFormat:@"%@",[brojLinije objectAtIndex:i]];
NSString *pocetno1 = [NSString stringWithFormat: @"%@", [pocetno objectAtIndex:i]];
NSString *tableSort = [NSString stringWithFormat: @"%@", [sortiranje objectAtIndex:i]];
image1 = [UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:[NSString stringWithFormat: @"http://www.busevi.com/images/stories/Red-Voznje/Gradski-Prevoz-BG/linija.%@.png", [urlSlike objectAtIndex:i ] ]]]];
NSData *data1 = [NSData dataWithData:UIImageJPEGRepresentation(image1, 0.1)];
NSManagedObjectContext *context = [self.fetchedResultsController managedObjectContext];
NSEntityDescription *entity = [[self.fetchedResultsController fetchRequest] entity];
NSManagedObject *newManagedObject = [NSEntityDescription insertNewObjectForEntityForName:[entity name] inManagedObjectContext:context];
NSString *pngFilePath = [NSString stringWithFormat:@"%@%@.jpg",desktopDir,[urlSlike objectAtIndex:i]];
[data1 writeToFile:pngFilePath atomically:YES];
[newManagedObject setValue:brojLinije1 forKey:@"brojLinije"];
[newManagedObject setValue:data1 forKey:@"imageData"];
[newManagedObject setValue:pocetno1 forKey:@"pocetnoStajaliste"];
[newManagedObject setValue:tableSort forKey:@"sort"];
NSLog(@"%d / 296", i);
}
[self.managedObjectContext save:&error];
}
我唯一知道的是图像分配频率(分配太多而没有时间自动释放)造成了问题,并且我已经尝试了目前为止我知道的所有方法,而且我已经看了很多"Instruments" 应用教程,只有一个帮助(找到填充虚拟内存的来源),但我仍然无法解决我的问题。
您可以在循环内部使用局部 autorelease pool 来立即释放在循环主体中创建的任何对象。
for (i = 0; i<296; i++) {
@autoreleasepool {
// loop body goes here...
}
}
采纳了你和我的所有建议和可能的解决方案,但是,很抱歉,none 成功了。
在这种情况下,当应用需要下载大量照片时,您确实应该使用 SDWebImageDownloader Class Reference。
我知道更改整个方法并意识到以前的方法(下载照片)是无用的,所以 HERE 是关于如何使用 SDWebImageDownloader Class 的教程和示例。祝你好运。
在使用 SDWebImage 框架时,我遇到了很多错误和应用程序无法解决的崩溃。如果要下载的图像数量低于 SDWebImage,那就太棒了,比方说 50。因为,当一张一张地下载 TableViewCell + 快速滚动(快速闪烁)中显示的图像时,应用程序会收到几次内存警告TableView 仍在滚动时的次数(SDWebImage 仅当 TableView 缓慢滚动或根本不滚动时才会清除内存)所以它使应用程序崩溃。
因此,我对下载 300 多张图片时应用程序崩溃的唯一安慰是简单的 Apple 方法,称为 dispatch_async
。更多信息 here.
这就是我解决问题的方法(我只需要将所有内容从我原来的 -(void)getdata
方法移动到 dispatch_async
块。完成!
所以现在看起来像这样:
-(void)getData {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSLog(@"Downloading Started");
slike = [[NSArray alloc]initWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"slike" ofType: @"plist"]];
brojevi = [[NSArray alloc]initWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"linije" ofType:@"plist"]];
pocetnaStajalista = [[NSArray alloc]initWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"pocetno" ofType:@"plist"]];
sort = [[NSArray alloc]initWithContentsOfFile:[[NSBundle mainBundle]pathForResource:@"sort" ofType:@"plist"]];
NSEntityDescription *entity = [NSEntityDescription entityForName:@"Linija" inManagedObjectContext:self.managedObjectContext];
NSString *brojLinije;
NSString *pocetnoStajaliste;
NSString *sortiranje;
NSData *data;
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *filePath = [NSString stringWithFormat:@"%@/%@", documentsDirectory,@"filename.png"];
for (int i = 0; i<314; i++) {
NSManagedObject *novaLinija = [[NSManagedObject alloc]initWithEntity:entity insertIntoManagedObjectContext:self.managedObjectContext];
brojLinije = [NSString stringWithFormat:@"%@",brojevi[i]];
pocetnoStajaliste = [NSString stringWithFormat:@"%@",pocetnaStajalista[i]];
data = [NSData dataWithContentsOfURL:[NSURL URLWithString:[NSString stringWithFormat: @"http://www.busevi.com/images/stories/Red-Voznje/Gradski-Prevoz-BG/linija.%@.png",slike[i]]]];
[data writeToFile:filePath atomically:YES];
sortiranje = [NSString stringWithFormat: @"%@", sort[i]];
[novaLinija setValue:data forKey:@"slikaLinije" ];
[novaLinija setValue:brojLinije forKey:@"brojLinije"];
[novaLinija setValue:pocetnoStajaliste forKey:@"pocetnoStajaliste"];
[novaLinija setValue:sortiranje forKey: @"sort"];
NSLog(@"%d / 314", i+1);
NSError *error;
[self.managedObjectContext save:&error];
} }
希望这对遇到同样问题的其他人有所帮助。祝你好运,编码愉快!
好吧..事情是这样的..我正在构建一个应用程序,当用户点击下载按钮时,它会下载一堆图像(准确地说是 296)。
在模拟器中一切正常,在我的 iPhone (4S) 上大约第 100 张图像上它崩溃并出现错误:
malloc: * mach_vm_map(size= "some random number") failed (error code= 3)* error: can't allocate region
libBacktraceRecording.dylib: allocate_free_list_pages() -- virtual memory exhausted!
这是我为下载这些图片而编写的代码:
-(void)getData
{
NSError *error;
int i;
NSArray *brojLinije = [[NSArray alloc] initWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"linije" ofType:@"plist"]];
NSArray *urlSlike = [[NSArray alloc] initWithContentsOfFile:[[NSBundle mainBundle]pathForResource:@"urlSlike" ofType:@"plist"]];
NSArray *pocetno = [[NSArray alloc] initWithContentsOfFile:[[NSBundle mainBundle]pathForResource:@"pocetno" ofType:@"plist"]];
NSArray *sortiranje = [[NSArray alloc] initWithContentsOfFile:[[NSBundle mainBundle]pathForResource:@"sort" ofType:@"plist"]];
NSArray*paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *desktopDir = [paths firstObject];
UIImage *image1 = [[UIImage alloc] init];
for (i = 0; i<296; i++) {
NSString *brojLinije1 = [NSString stringWithFormat:@"%@",[brojLinije objectAtIndex:i]];
NSString *pocetno1 = [NSString stringWithFormat: @"%@", [pocetno objectAtIndex:i]];
NSString *tableSort = [NSString stringWithFormat: @"%@", [sortiranje objectAtIndex:i]];
image1 = [UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:[NSString stringWithFormat: @"http://www.busevi.com/images/stories/Red-Voznje/Gradski-Prevoz-BG/linija.%@.png", [urlSlike objectAtIndex:i ] ]]]];
NSData *data1 = [NSData dataWithData:UIImageJPEGRepresentation(image1, 0.1)];
NSManagedObjectContext *context = [self.fetchedResultsController managedObjectContext];
NSEntityDescription *entity = [[self.fetchedResultsController fetchRequest] entity];
NSManagedObject *newManagedObject = [NSEntityDescription insertNewObjectForEntityForName:[entity name] inManagedObjectContext:context];
NSString *pngFilePath = [NSString stringWithFormat:@"%@%@.jpg",desktopDir,[urlSlike objectAtIndex:i]];
[data1 writeToFile:pngFilePath atomically:YES];
[newManagedObject setValue:brojLinije1 forKey:@"brojLinije"];
[newManagedObject setValue:data1 forKey:@"imageData"];
[newManagedObject setValue:pocetno1 forKey:@"pocetnoStajaliste"];
[newManagedObject setValue:tableSort forKey:@"sort"];
NSLog(@"%d / 296", i);
}
[self.managedObjectContext save:&error];
}
我唯一知道的是图像分配频率(分配太多而没有时间自动释放)造成了问题,并且我已经尝试了目前为止我知道的所有方法,而且我已经看了很多"Instruments" 应用教程,只有一个帮助(找到填充虚拟内存的来源),但我仍然无法解决我的问题。
您可以在循环内部使用局部 autorelease pool 来立即释放在循环主体中创建的任何对象。
for (i = 0; i<296; i++) {
@autoreleasepool {
// loop body goes here...
}
}
采纳了你和我的所有建议和可能的解决方案,但是,很抱歉,none 成功了。
在这种情况下,当应用需要下载大量照片时,您确实应该使用 SDWebImageDownloader Class Reference。
我知道更改整个方法并意识到以前的方法(下载照片)是无用的,所以 HERE 是关于如何使用 SDWebImageDownloader Class 的教程和示例。祝你好运。
在使用 SDWebImage 框架时,我遇到了很多错误和应用程序无法解决的崩溃。如果要下载的图像数量低于 SDWebImage,那就太棒了,比方说 50。因为,当一张一张地下载 TableViewCell + 快速滚动(快速闪烁)中显示的图像时,应用程序会收到几次内存警告TableView 仍在滚动时的次数(SDWebImage 仅当 TableView 缓慢滚动或根本不滚动时才会清除内存)所以它使应用程序崩溃。
因此,我对下载 300 多张图片时应用程序崩溃的唯一安慰是简单的 Apple 方法,称为 dispatch_async
。更多信息 here.
这就是我解决问题的方法(我只需要将所有内容从我原来的 -(void)getdata
方法移动到 dispatch_async
块。完成!
所以现在看起来像这样:
-(void)getData {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSLog(@"Downloading Started");
slike = [[NSArray alloc]initWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"slike" ofType: @"plist"]];
brojevi = [[NSArray alloc]initWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"linije" ofType:@"plist"]];
pocetnaStajalista = [[NSArray alloc]initWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"pocetno" ofType:@"plist"]];
sort = [[NSArray alloc]initWithContentsOfFile:[[NSBundle mainBundle]pathForResource:@"sort" ofType:@"plist"]];
NSEntityDescription *entity = [NSEntityDescription entityForName:@"Linija" inManagedObjectContext:self.managedObjectContext];
NSString *brojLinije;
NSString *pocetnoStajaliste;
NSString *sortiranje;
NSData *data;
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *filePath = [NSString stringWithFormat:@"%@/%@", documentsDirectory,@"filename.png"];
for (int i = 0; i<314; i++) {
NSManagedObject *novaLinija = [[NSManagedObject alloc]initWithEntity:entity insertIntoManagedObjectContext:self.managedObjectContext];
brojLinije = [NSString stringWithFormat:@"%@",brojevi[i]];
pocetnoStajaliste = [NSString stringWithFormat:@"%@",pocetnaStajalista[i]];
data = [NSData dataWithContentsOfURL:[NSURL URLWithString:[NSString stringWithFormat: @"http://www.busevi.com/images/stories/Red-Voznje/Gradski-Prevoz-BG/linija.%@.png",slike[i]]]];
[data writeToFile:filePath atomically:YES];
sortiranje = [NSString stringWithFormat: @"%@", sort[i]];
[novaLinija setValue:data forKey:@"slikaLinije" ];
[novaLinija setValue:brojLinije forKey:@"brojLinije"];
[novaLinija setValue:pocetnoStajaliste forKey:@"pocetnoStajaliste"];
[novaLinija setValue:sortiranje forKey: @"sort"];
NSLog(@"%d / 314", i+1);
NSError *error;
[self.managedObjectContext save:&error];
} }
希望这对遇到同样问题的其他人有所帮助。祝你好运,编码愉快!