2011-03-03 58 views
6

我經常嘗試修復當我使用我的iPhone用於其他內存飢餓的東西時出現的錯誤,並且它需要釋放一些內存並因此從我的應用程序中卸載一些視圖。我發現這很難模擬當我需要它,所以我決定,將嘗試分配儘可能多的內存,並強制我的測試應用程序釋放未使用的意見等。如何使iPhone應用程序快速填充內存

我試過一些簡單的事情,幾百毫秒,但出於某種原因沒有做任何事情

[[NSData alloc] initWithBytes:malloc(2048 * 1024) length:2048 * 1024]; 

儀器顯示該Apps是越來越大,遠遠超出了(MBS數百分配)iPhone的內存容量,但我甚至不得到內存警告並且它根本不影響其他應用程序。有沒有一些保障措施,以某種方式阻止iPhone應用程序形式做這樣的事情?或者我對iphone的工作原理有錯誤嗎? 當你面對它時,你如何解決這個問題?

編輯:我正在我的設備上的應用程序,我是不是能夠得到卸載模擬器上我的意見,即使我模擬內存警告(這有時會工作,但很少)

EDIT2:爲bbum指出出的問題的確是虛擬分配,簡單的memset後分配的伎倆

void *data = malloc(1024 * 1024); 
memset(data, 0, 1024 * 1024); 

回答

4

最有可能的,正在發生的事情是虛擬尋址你背後一個調皮位。也就是說,應用程序可以自由保留高達4GB的32位可用地址空間(小於4GB,真的,因爲存在由各種系統組件引起的碎片)。

當您做malloc(REALLYBIGNUMBER)時,系統使用vm_allocate()來完成請求。馬克內存管理器把你的地址交給你,但實際上並沒有用真實的內存來支持它(有點像美國經濟在市場上有很多$$$沒有任何實際資產支持)。

物理內存將僅在您向內存寫入(或技術上講,讀取)某些內容時使用。它只會一頁接一頁地發生。

所以,如果你要走過4096(頁面大小)步長的分配緩衝區並寫入一個字節,你很快會看到真正的內存被佔用。

+0

您是對的!我懷疑有類似的詭計,但我不知道簡單的讀/寫能解決它。謝謝! – Lope 2011-03-03 19:40:30

4

你能不只是模擬使用「設備」菜單中的模擬內存警告?

+0

我試過了,但即使我嘗試模擬內存警告我的意見不會被卸載,所以它沒有幫助 – Lope 2011-03-03 18:49:07

+0

原來我沒有正確使用模擬器(不知道它甚至可能:)),現在它做它應該的,所以感謝您指出我的權利方向。但我仍然想知道我的問題的答案,所以我可以在設備上測試它 – Lope 2011-03-03 19:08:43

0

您正在設備上運行的進程或模擬器上運行儀器嗎?
我想在模擬器中它使用的是你的Mac的內存,它明顯比iPhone的大。嘗試在設備上運行它,看看會發生什麼?

迪斯科

+0

我在設備上運行(iphone 4),但它仍然可以分配數百兆內存,而不會發生任何事情 – Lope 2011-03-03 18:48:31

1

在分配內存塊之後,需要對內存塊進行bzero(或以其他方式寫入每個頁面),以便虛擬內存系統創建塊中的所有頁面並將它們標記爲常駐+髒。

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"); 
    } 

} 

完成這種方式後,儀器就會看到內存分配。
memset溶液bbum建議可能會做的伎倆,而不是留在原地的幫助,以確保我不要錯誤出貨的dataWithBytesNoCopy: length: freeWhenDone:

警告和日誌。
如果你添加一些這個代碼的一個項目,我建議你讓他們也(和打開款待的警告當作錯誤選項)..

+0

看起來很有趣,你如何在你的應用中調用它?你有一些調試按鈕或什麼? – Lope 2011-03-04 13:17:16

+0

我在applicationDidFinishLaunching中調用它:如果宏MEMORY_STRESS_TEST_SCARCITY_ENABLED設置爲1,它將使用並保存內存。否則,這將是一個無操作。但是你可以從應用中的任何位置調用它,甚至多次。你也可以用一個首選項替換宏,這個首選項可以在Debug窗口中配置。 – Guillaume 2011-03-04 13:39:04