2011-03-24 4 views
3

아래의 코드를 실행하면 응용 프로그램이 아래의 스택 추적과 충돌합니다 (~ 30 초 후). 나는 가비지 컬렉터가이 기억을 정리할 것으로 기대하기 때문에 이것을 매우 이상하게 생각한다. 우리 응용 프로그램은 비슷한 패턴을 가지고 있으며 유사한 스택 추적으로 중단됩니다.NSObject를 인스턴스화하면 메모리 부족 문제가 발생합니다.

NSObject 멤버를 인스턴스화하는 줄을 주석 처리하면 응용 프로그램이 충돌없이 실행됩니다. 바이트 배열을 인스턴스화하는 행을 주석 처리하면 앱이 더 오래 실행되지만 여전히 충돌합니다.

인스트루먼트는 앱에 대한 매우 안정한 라이브 바이트를보고하고 계측기로 인해 앱이 충돌하지 않고 훨씬 오래 실행되지만 여전히 충돌합니다 (~ 10 분 후). 라이브 바이트를 사용하면 가비지 컬렉터가 작동하는 것처럼 느껴집니다.

코드 :

using System.Threading; 
using MonoTouch.Foundation; 
using MonoTouch.UIKit; 

namespace MyExample 
{ 
    public class Application 
    { 
     static void Main (string[] args) 
     { 
      UIApplication.Main(args); 
     } 
    } 

    public partial class AppDelegate : UIApplicationDelegate 
    { 
     public override bool FinishedLaunching (UIApplication app, NSDictionary options) 
     { 
      Thread testThread = new Thread(BreakMe); 
      testThread.Start(); 

      window.MakeKeyAndVisible(); 
      return true; 
     } 

     private void BreakMe() 
     { 
      while(true) 
      { 
       using (var arPool = new NSAutoreleasePool()) 
       { 
        MyGarbage garbage = new MyGarbage(); 
       } 
      } 
     } 

     private class MyGarbage 
     { 
      byte[] _Foo = new byte[100000]; 
      NSObject _Bar = new NSObject(); 
     } 
    } 
} 

응용 프로그램 출력 : 당신은 가비지 컬렉터와 경주에서 할당을 넣어 가지고

Mprotect failed at 0x493c000 (length 4096) with errno 12 
Stacktrace: 

    at (wrapper managed-to-native) System.Array.CreateInstanceImpl (System.Type,int[],int[]) <0xffffffff> 
    at System.Array.CreateInstance (System.Type,int[]) <0x000bc> 
    at System.Array.CreateInstance (System.Type,int) <0x00057> 
    at System.MonoCustomAttrs.GetCustomAttributes (System.Reflection.ICustomAttributeProvider,System.Type,bool) <0x000db> 
    at System.MonoCustomAttrs.GetCustomAttribute (System.Reflection.ICustomAttributeProvider,System.Type,bool) <0x00033> 
    at System.Attribute.GetCustomAttribute (System.Reflection.MemberInfo,System.Type,bool) <0x0003f> 
    at MonoTouch.ObjCRuntime.Class.GetHandle (System.Type) <0x00037> 
    at MonoTouch.Foundation.NSObject.AllocIfNeeded() <0x00063> 
    at MonoTouch.Foundation.NSObject..ctor (MonoTouch.Foundation.NSObjectFlag) <0x00027> 
    at MonoTouch.Foundation.NSAutoreleasePool..ctor() <0x00037> 
    at MyExample.AppDelegate.BreakMe() [0x00000] in Main.cs:30 
    at (wrapper runtime-invoke) object.runtime_invoke_dynamic (intptr,intptr,intptr,intptr) <0x000cb> 

Native stacktrace: 

    0 MyExample      0x002db308 mono_handle_native_sigsegv + 404 
    1 MyExample      0x002fa5dc sigabrt_signal_handler + 148 
    2 libsystem_c.dylib     0x369c972f _sigtramp + 42 
    3 libsystem_c.dylib     0x369be3bb pthread_kill + 58 
    4 libsystem_c.dylib     0x369b6bff abort + 78 
    5 MyExample      0x0041e484 GC_remap + 200 
    6 MyExample      0x00411ee4 GC_allochblk_nth + 1536 
    7 MyExample      0x00411894 GC_allochblk + 96 
    8 MyExample      0x0041d94c GC_new_hblk + 116 
    9 MyExample      0x00413c3c GC_allocobj + 188 
    10 MyExample      0x0041859c GC_generic_malloc_inner + 352 
    11 MyExample      0x004187ac GC_generic_malloc + 132 
    12 MyExample      0x00418c60 GC_malloc + 208 
    13 MyExample      0x003a67dc mono_object_allocate + 64 
    14 MyExample      0x003a7240 mono_array_new_full + 828 
    15 MyExample      0x00341324 ves_icall_System_Array_CreateInstanceImpl + 896 
    16 MyExample      0x0012cf3c (wrapper managed-to-native) System.Array:CreateInstanceImpl (System.Type,int[],int[]) + 80 
    17 MyExample      0x0012d23c System.Array:CreateInstance (System.Type,int) + 88 
    18 MyExample      0x0018b70c System.MonoCustomAttrs:GetCustomAttributes (System.Reflection.ICustomAttributeProvider,System.Type,bool) + 220 
    19 MyExample      0x0018b560 System.MonoCustomAttrs:GetCustomAttribute (System.Reflection.ICustomAttributeProvider,System.Type,bool) + 52 
    20 MyExample      0x00131fd0 System.Attribute:GetCustomAttribute (System.Reflection.MemberInfo,System.Type,bool) + 64 
    21 MyExample      0x000795ec MonoTouch.ObjCRuntime.Class:GetHandle (System.Type) + 56 
    22 MyExample      0x00077e60 MonoTouch.Foundation.NSObject:AllocIfNeeded() + 100 
    23 MyExample      0x0007779c MonoTouch.Foundation.NSObject:.ctor (MonoTouch.Foundation.NSObjectFlag) + 40 
    24 MyExample      0x00074d10 MonoTouch.Foundation.NSAutoreleasePool:.ctor() + 56 
    25 MyExample      0x00002c34 MyExample.AppDelegate:BreakMe() + 164 
    26 MyExample      0x001f3e3c (wrapper runtime-invoke) object:runtime_invoke_dynamic (intptr,intptr,intptr,intptr) + 204 
    27 MyExample      0x002c4658 mono_jit_runtime_invoke + 3032 
    28 MyExample      0x003a34a8 mono_runtime_invoke + 140 
    29 MyExample      0x003a48f0 mono_runtime_delegate_invoke + 136 
    30 MyExample      0x003cb31c start_wrapper + 752 
    31 MyExample      0x003f09a0 thread_start_routine + 240 
    32 MyExample      0x0041f9ac GC_start_routine + 132 
    33 libsystem_c.dylib     0x369be311 _pthread_start + 248 
    34 libsystem_c.dylib     0x369bfbbc start_wqthread + 0 
+0

똑같은 코드를 테스트했는데 충돌이 없습니다. 그러나 스레드에'NSAutoreleasePool' **를 한 번 ** 적용하십시오. 그런 다음'using' 블록 안에'while' 코드를 입력하십시오. –

+0

iPad 시뮬레이터에서 충돌이 발생하지 않도록하고 iOS 4.3이 적용된 iPad 1에서 실행 중이어야합니다. – tohlsen

+0

@Dimitris가 맞습니다. 코드에 결함이 있습니다 : 구문을 사용하지 않고 NSAutoreleasePool을 필요로 할 수 있습니다. 수정하여 문제가 해결되는지 확인하십시오. 시뮬레이터는 더 많은 RAM, 빠른 CPU 등에 액세스 할 수 있기 때문에 장치와 매우 다릅니다. 메모리 문제는 장치에서 더 빨리 발생합니다. – jonathanpeppers

답변

2

메모리 관리자 문제 인 Why is our MonoTouch app breaking in the garbage collector? It is not out of memory에서이 문제가 해결 된 것 같습니다. 스택 트레이스는 나에게 익숙하다.

+0

MonoTouch 자체에서 문제가 발생했을 때이 문제를 해결하기 위해 수 주일을 보냈다는 점에서 매우 실망 스럽습니다. 그리고 나는 문제가있는 곳에서 자신의 소스 코드를 지적하기 위해 노벨 외부의 누군가가 필요하다는 사실에 좌절감을 느낍니다. 유감스럽게 생각하지만 MonoTouch가 플랫폼을 지원해야한다는 의견을 듣고 싶습니다. – tohlsen

+0

오늘 확인 테스트를 위해 실제로 테스트를 진행하여 실제로 우리가 가진 문제입니다. MonoTouch 3.x를 사용하여 GC.Collect를 코드 전체에 주입 한 후에도 (그리고 성능을 죽이는) 우리는 여전히 안정성 문제가있었습니다. 나는 이것을 꺼내 MonoTouch 4.0.3으로 업그레이드했다. 결과에 대한 자세한 내용은 내일을 ... – tohlsen

+0

MonoTouch 버그 데이터베이스 및 기타 보고서를 포함하여이 문서를 파헤칩니다. 우리가 재현 할 수있는 실패를 줄 수있게되면 Geoff는 매우 좋았습니다. 심지어 시간이 걸렸습니다. 안정적인 경우 대신 내 대답을 수락하십시오. 8-) – mj2008

1

. 당신이 당신의 데모에 대한 간단한 변경 및 추가하는 경우 :

System.GC.Collect(); 

를 루프에서, 당신은 더 이상 충돌 볼 수 없습니다.

여기서 일어나는 일은 가능한 한 빨리 할당하는 것입니다. GC에서 메모리가 부족하면 힙이 확장되고 수집됩니다. 루프가 실행되는 다음 몇 번은 확장 된 힙 (heap)으로 인해 다시 수집해야하기 전에 조금 더 오래 실행되지만, 결국 경주는 손실됩니다.

위에서 언급 한 부분 수정을하면 내가 포기하기 전에 테스트를 10 분 동안 실행할 수 있습니다.

+0

답변을 드릴뿐만 아니라 이유를 설명해 주셔서 감사합니다. 좋은 일과 다시, 고마워! – tohlsen

+0

할당 자의 수명이 다되었을 때 왜 MonoTouch가 가비지 수집을 할당 자 안에서 실행할 수 없습니까? 그렇게하지 않으면 할당에서 충돌을 일으키지 않도록하는 유일한 방법은 모든 할당 전에 GC.Collect를 호출하는 것입니다. 저장소에있는 앱의 경우 참조가 유지되는 객체 측면에서 매우 잘 작동한다고해도 GC_remap이 무작위로 크래시가 발생합니다 (즉, 자주 할당하더라도 항상 동일한 양의 메모리를 참조합니다). – Mike

+0

그렇지만 다른 여러 요소가 있습니다. 최종 생성 대기열에 몇 개의 객체가 있습니까? finalizers가 달릴 시간이 있었습니까? –