我经常尝试修复当我将iphone用于其他内存饥饿时出现的错误,它需要释放一些内存,从而从我的应用程序卸载一些视图。我发现这很难在我需要时进行模拟,所以我决定尽量分配尽可能多的内存并强制我测试的应用程序释放未使用的视图等。
我尝试了一些简单的事情,每隔几百毫秒调用一次,但由于某些原因它没有做任何事情
[[NSData alloc] initWithBytes:malloc(2048 * 1024) length:2048 * 1024];
仪器显示应用程序越来越大,远远超出了iphone的内存容量(分配了数百mbs),但我甚至没有得到内存警告,它根本不会影响其他应用程序。是否有一些安全措施可以防止iphone app形式做这样的事情?或者我对iphone如何工作的假设有些错误? 当你面对这个问题时,你如何解决这个问题?
编辑:我正在设备上运行我的应用程序,即使我模拟了内存警告,我也无法在模拟器上卸载我的视图(这有时可以工作,但很少) EDIT2:因为bbum指出问题确实在虚拟分配中,分配后的简单memset做了招数void *data = malloc(1024 * 1024);
memset(data, 0, 1024 * 1024);
答案 0 :(得分:4)
您是否可以使用“设备”菜单在模拟器中模拟内存警告?
答案 1 :(得分:4)
最有可能的是,正在发生的事情是你背后的一点点虚拟寻址。
即,应用程序可以自由保留最多可用的4GB 32位地址空间(实际上小于4GB,因为各种系统碎片会造成碎片)。
执行malloc(REALLYBIGNUMBER)
后,系统会使用vm_allocate()
来完成请求。机器人记忆管理器会将你的地址发回给你,但实际上并没有用真实记忆来支持它(有点像美国经济在市场上有大量的$$$而没有真正的资产支持)。
物理内存仅在您向内存写入(或技术上,读取)内容时使用。它只会逐页发生。
因此,如果您以4096(页面大小)的步幅浏览分配的缓冲区并写入一个字节,您很快就会看到正在使用的内存。
答案 2 :(得分:2)
以下是我模拟使用大块内存的方法。
#define MEGA (1024 * 1024)
- (void)stressTestTheApplicationBySimulatingMemoryScarcity {
NSUInteger sizeInMB = 20; // Size in MB. The higher, the more memory will be used here, leaving less for the application
// On iPad: 30 seems to be the upper limit you can ask. YMMV
#if MEMORY_STRESS_TEST_SCARCITY_ENABLED
#warning MEMORY_STRESS_TEST_SCARCITY_ENABLED - THIS SHOULD NOT HAPPEN IN PRODUCTION
#else
return;
#endif
NSLog(@"MEMORY STRESS TEST ENABLED (%dMB)", sizeInMB);
void * unusedMemoryBufferToSimulateMemoryScarcity = NSZoneCalloc(NSDefaultMallocZone(), sizeInMB * MEGA, 1);
if (NULL == unusedMemoryBufferToSimulateMemoryScarcity) {
NSLog(@"MEMORY STRESS TEST FAILED: Was unable to allocate requested memory");
return;
}
dataToRetainToSimulateMemoryScarcity = [[NSData dataWithBytesNoCopy:unusedMemoryBufferToSimulateMemoryScarcity
length:sizeInMB * MEGA
freeWhenDone:YES] retain];
if (dataToRetainToSimulateMemoryScarcity == nil) {
NSLog(@"Failed to retain data to simulate memory scarcity");
}
}
通过这种方式,仪器可以看到内存分配
bbum建议的memset
解决方案可能已经完成了诀窍,而不是dataWithBytesNoCopy: length: freeWhenDone:
留下的警告和日志有助于确保我不会错误地发货 如果您将一些此代码添加到项目中,我建议您保留它们(并打开将警告视为错误选项)..
答案 3 :(得分:1)
在分配内存块后,您需要对内存块进行bzero(或以其他方式写入每个页面),以便虚拟内存系统创建块中的所有页面并将其标记为驻留+脏。
答案 4 :(得分:0)
您是否在设备或模拟器上运行的进程上运行仪器? 我认为在模拟器中它使用你的Mac内存,这显然比iPhone的内存大。尝试在设备上运行它,看看会发生什么?
迪斯科