Search Unity

"System.String doesn't implement interface System.Collections.IEnumerator" crash

Discussion in 'iOS and tvOS' started by FeatureCreep, Jan 28, 2013.

  1. FeatureCreep

    FeatureCreep

    Joined:
    Oct 5, 2012
    Posts:
    6
    Using Unity 3.5.6f4 to build for the iPad, we would "randomly" see this error in the Xcode output:

    System.String doesn't implement interface System.Collections.IEnumerator
    * Assertion: should not be reached at mini-trampolines.c:183

    Looking at the stack trace in Xcode, I tracked down the offending statement to a foreach block in a UI framework assembly (DLL) that is used by our project. It turns out, that this is a very tricky problem to find and fix, I'm sharing on the forum for "the greater good", since I have benefited many times from development forums on the Internet.

    This problem only occurs on iOS because it is due to a limitation in the Ahead-Of-Time (AOT) compiler that is used to compile Mono byte code into native code. Thus, your app probably runs fine in the Editor, WebPlayer, Windows, Mac, etc. But, on iOS, it will crash, sometimes the crashes will appear to be random.

    The reason this crash is occurring is because the IEnumerable<T>.GetEnumerator() is being used instead of the non-generic IEnumerable.GetEnumerator() to get an enumerator object used by foreach iteration blocks. Since IEnumerable<T> is a type of interface dispatch not supported by full AOT (see http://www.mono-project.com/AOT), the 'enumerator' returned by this method is actually a string object (I don't know why), which results in a crash.

    This problem may appear to be random because the 'GetEnumerator()' method "found" by foreach could be the System.Collections.IEnumerable (non-generic) interface implemented by the standard Mono/.NET collections, which works as expected. The ordering of the methods is not consistent, so sometimes the generic interface method is used, making the crash seem random.

    I'm surprised that collections being iterated by foreach aren't crashing left and right due to this issue, but I assume that System.Collections.IEnumerable (non-generic) is being found by foreach most of the time or perhaps it's because when this code is in a separate assembly it gives the AOT compiler additional trouble resolving to the appropriate GetEnumerator() method.

    Either way, here is an AOT-safe method to iterate over an IEnumerable collection. Replace the foreach statement(s) where the crash is occurring with this method.

    Code (csharp):
    1.  
    2. using System;
    3. using System.Linq;
    4. using System.Collections;
    5. using System.Reflection;
    6.  
    7. namespace Aperture
    8. {
    9.     public class AotSafe
    10.     {
    11.         public static void ForEach<T>(object enumerable, Action<T> action)
    12.         {
    13.             if (enumerable == null)
    14.             {
    15.                 return;
    16.             }
    17.  
    18.             Type listType = enumerable.GetType().GetInterfaces().First(x => !(x.IsGenericType)  x == typeof(IEnumerable));
    19.             if (listType == null)
    20.             {
    21.                 throw new ArgumentException("Object does not implement IEnumerable interface", "enumerable");
    22.             }
    23.  
    24.             MethodInfo method = listType.GetMethod("GetEnumerator");
    25.             if (method == null)
    26.             {
    27.                 throw new InvalidOperationException("Failed to get 'GetEnumberator()' method info from IEnumerable type");
    28.             }
    29.  
    30.             IEnumerator enumerator = null;
    31.             try
    32.             {
    33.                 enumerator = (IEnumerator)method.Invoke(enumerable, null);
    34.                 if (enumerator is IEnumerator)
    35.                 {
    36.                         while (enumerator.MoveNext())
    37.                         {
    38.                             action((T)enumerator.Current);
    39.                         }
    40.                 }
    41.                 else
    42.                 {
    43.                     UnityEngine.Debug.Log(string.Format("{0}.GetEnumerator() returned '{1}' instead of IEnumerator.",
    44.                         enumerable.ToString(),
    45.                         enumerator.GetType().Name));
    46.                 }
    47.             }
    48.             finally
    49.             {
    50.                 IDisposable disposable = enumerator as IDisposable;
    51.                 if (disposable != null)
    52.                 {
    53.                     disposable.Dispose();
    54.                 }
    55.             }
    56.         }
    57.     }
    58. }
    59.  
    Example usage:

    Code (csharp):
    1.  
    2.                 AotSafe.ForEach<object>(ItemsSource, (item) =>
    3.                 {
    4.                     // Do something with item from collection ItemsSource                  
    5.                 });
    6.  
    where ItemsSource is an IEnumerable container.
     
    Last edited: Jan 28, 2013
  2. xavicampos

    xavicampos

    Joined:
    Mar 21, 2013
    Posts:
    1
    It works!

    Thank you so much!!!
     
  3. Mantas-Puida

    Mantas-Puida

    Joined:
    Nov 13, 2008
    Posts:
    1,864
    @FeatureCreep, I would appreciate bug report with repro case attached.
    Thanks!
     
  4. JaredThirsk

    JaredThirsk

    Joined:
    Jan 17, 2010
    Posts:
    38
    Did you try simply casting the IEnumerable<> to IEnumerable? i.e.

    Code (csharp):
    1.  
    2. IEnumerable<MyType> items;
    3.  
    4. foreach(MyType item in (IEnumerable)items)
    5. {
    6.    // ...
    7. }
    8.  
     
  5. FeatureCreep

    FeatureCreep

    Joined:
    Oct 5, 2012
    Posts:
    6
    @JaredThirsk: unfortunately, explicit casting doesn't fix the problem.

    IEnumerable<T> inherits from IEnumerable, so casting to "IEnumerable" doesn't guarantee you're going to get the IEnumerable (non-generic) implementation. The first interface that matches IEnumerable will be returned by the cast (which could be IEnumerable<T>).
     
  6. JaredThirsk

    JaredThirsk

    Joined:
    Jan 17, 2010
    Posts:
    38
    Are you sure about this? Did you verify my approach doesn't work via a test?

    I thought the problem here was with generic interface dispatch (i.e. IEnumerable<T>), and my understanding is there is only one implementation of the non-generic IEnumerable.GetEnumerator(), and by first casting to IEnumerable (nongeneric), the generic interface dispatch problem is avoided.

    As far as the language is concerned, if you are working with IEnumerable, and request "IEnumerator IEnumerable.GetEnumerator()", it should not matter that the class also implements IEnumerable<T>, which has a method "IEnumerator<T> IEnumerable<T>.GetEnumerator()". IEnumerable<T>'s inheritance simply means the class must also implement IEnumerable -- I don't understand why it would confuse implementations. (As far as mono's IMT stuff is concerned, I don't fully understand how it works or the implications of all the bugs Unity's now ancient 2.6.5 version has.)
     
  7. FredDeschenes

    FredDeschenes

    Joined:
    Mar 15, 2013
    Posts:
    21
    I seem to be having the same issue (also randomly happens), but either my stack-trace is wrong or the issue can have a different cause. The stack-trace looks like this :

    Code (csharp):
    1.  
    2. Thread 20 Crashed:
    3. 0   SomeAppName         0x01242310 g_logv + 160
    4. 1   SomeAppName         0x01242330 g_log + 28
    5. 2   SomeAppName         0x0115827c mono_convert_imt_slot_to_vtable_slot + 216
    6. 3   SomeAppName         0x01155cfc mono_magic_trampoline + 788
    7. 4   SomeAppName         0x00a8fa34 generic_trampoline_0 + 116
    8. 5   SomeAppName         0x00b53cac m_companyName_communications_CommunicationManager_communicationsChannel_OnMessageReceived_object + 40
    9. 6   SomeAppName         0x00b4d698 m_companyName_communications_channel_AbstractChannel_RaiseMessageReceived_object + 96
    10. 7   SomeAppName         0x00b4ffac m_companyName_communications_channel_socket_SocketChannel_connection_OnMessageReceived_byte__ + 108
    11. 8   SomeAppName         0x00b521bc m_companyName_communications_channel_socket_SocketClient_ReceiveCallback_System_IAsyncResult + 2044
    12. 9   SomeAppName         0x00322aa0 m_System_Net_Sockets_Socket_SocketAsyncResult_Complete + 780
    13. 10  SomeAppName         0x00324064 m_System_Net_Sockets_Socket_Worker_Receive + 60
    14. 11  SomeAppName         0x009e2868 m_wrapper_runtime_invoke_object_runtime_invoke_dynamic_intptr_intptr_intptr_intptr + 200
    15. 12  SomeAppName         0x011443a4 mono_jit_runtime_invoke + 2152
    16. 13  SomeAppName         0x011e7424 mono_runtime_invoke + 132
    17. 14  SomeAppName         0x011ec218 mono_runtime_invoke_array + 1448
    18. 15  SomeAppName         0x011ec610 mono_message_invoke + 444
    19. 16  SomeAppName         0x01210600 mono_async_invoke + 124
    20. 17  SomeAppName         0x012114f8 async_invoke_io_thread + 452
    21. 18  SomeAppName         0x012186d8 start_wrapper + 496
    22. 19  SomeAppName         0x0123570c thread_start_routine + 284
    23. 20  SomeAppName         0x01251908 GC_start_routine + 92
    24. 21  libsystem_c.dylib   0x3a68830e _pthread_start + 306
    25. 22  libsystem_c.dylib   0x3a6881d4 thread_start + 4
    26.  
    but the 'OnMessageReceived' method looks like this :

    Code (csharp):
    1.  
    2. private void communicationsChannel_OnMessageReceived(object message)
    3. {
    4.  
    5.     HandleInboundMessage(message);
    6.  
    7. }
    8.  
    BUT the 'HandleInboundMessage' method does have a foreach in it :

    Code (csharp):
    1.  
    2. private void HandleInboundMessage(object message)
    3. {
    4.     if (message is IList)
    5.     {
    6.         foreach (object childMessage in (IList)message)
    7.         {
    8.             HandleInboundMessage(childMessage);
    9.         }
    10.     }
    11.     else if (message is AbstractNotification)
    12.     {
    13.         OnServerNotification((AbstractNotification)message);
    14.     }
    15.     else if (message is AbstractResponse)
    16.     {
    17.         OnServerResponse((AbstractResponse)message);
    18.     }
    19.     else
    20.     {
    21.         OnUnknownMessageType(message);
    22.     }
    23. }
    24.  
    Since I'm having issues connecting the iPad to MonoDevelop to debug the application I'm guessing that the method is being called with a list (which would be a 'List<object>' instance containing 'AbstractResponse' instances), but anyway here's the exact message I'm getting :

    Code (csharp):
    1.  
    2. System.String doesn't implement interface System.Collections.IEnumerator
    3. * Assertion: should not be reached at mini-trampolines.c:183
    4.  
    which seems to be the exact same thing as you guys.

    Anyway I will try the suggested fix and come back with some news soon.

    EDIT : Applying the fix from OP in the 'foreach' in 'HandleInboundMessage' fixed seems to have fixed the issue, so apparently the stack traces from iOS devices cannot be trusted... Anyway thanks for the fix/help FeatureCreep!
     
    Last edited: Sep 4, 2013
  8. Aurigan

    Aurigan

    Joined:
    Jun 30, 2013
    Posts:
    291
    @FeatureCreep - HUGE thank you!

    I was getting this error using UniParse serialization on iOS only, replacing all the foreach statements with your class seems to have resolved the "System.String doesn't implement interface System.Collections.IEnumerator" crashes.
     
  9. Dustin-Horne

    Dustin-Horne

    Joined:
    Apr 4, 2013
    Posts:
    4,568
    There are a couple of different ways you can solve this... unfortunately none of them are ideal.

    1. Solution provided by FeatureCreep
    Pros: Retains typing.
    Cons: Uses Invoke - should be used sparingly if possible as there's a performance penalty

    2. Downcasting to IEnumerable as suggested by JaredThirsk
    Pros: Works with minimal amount of code
    Cons: Will cause boxing/unboxing for lists with a Value Type - IEnumerable.GetEnumerator() returns type "object" which will have to be cast back to your original type. For example:

    Code (csharp):
    1.  
    2. public List<T> GetList(IEnumerable<T> items)
    3. {
    4.      var result = new List<T>();
    5.      var oldItems = (IEnumerable)items;
    6.  
    7.      foreach(var obj in oldItems)
    8.      {
    9.             result.Add((T)obj);
    10.      }
    11.  
    12.      return result;
    13. }
    14.  
    3. Convert to Array
    Pros: Simple to implement. Prevents boxing and unboxing.
    Cons: Higher memory usage for value types as the values would be copied to the new array rather than referenced.

    Example:
    Code (csharp):
    1.  
    2. public List<T> GetList(IEnumerable<T> items)
    3. {
    4.       var result = new List<T>();
    5.  
    6.       var itemsArray = items.ToArray();
    7.       for(var i = 0; i < itemsArray.Length; i++)
    8.       {
    9.             result.Add(itemsArray[i]);          
    10.       }
    11.  
    12.       return result;
    13. }
    14.  
    Personally I would go with option #3 unless you're dealing with a massive list of value types (i.e. List<float>).

    There may potentially be another route which I'm investigating... My latest JSON .NET version that will be published soon uses the 3rd approach as it should offer the best performance. But, there is also the possibility of creating a delegate wrapper around GetEnumerator and using it to call the function. It would be a hybrid approach. Essentially it would be FeatureCreep's approach but rather than using Invoke it would use a delegate proxy to execute the function which offers far superior performance but I'm not positive yet that it will work with AOT.
     
  10. Dustin-Horne

    Dustin-Horne

    Joined:
    Apr 4, 2013
    Posts:
    4,568
    Sorry... used the wrong CreateDelegate implementation in my first post so I deleted it. Here is the corrected version. I realized that ToArray may not work... But I was bothered by the Invoke in FeatureCreep's suggestion so I replaced it with a delegate. I'd love for someone to test this and let me know if it works properly. It should perform much quicker:

    Code (csharp):
    1.  
    2. using System;
    3. using System.Collections;
    4. using System.Linq;
    5.  
    6. namespace Aperture
    7. {
    8.     public class AotSafe
    9.     {
    10.         //Delegate to return IEnumerator
    11.         private delegate IEnumerator GetEnumerator();
    12.  
    13.         public static void ForEach<T>(object enumerable, Action<T> action)
    14.         {
    15.             if (enumerable == null)
    16.                 return;
    17.  
    18.             var listType = enumerable.GetType().GetInterfaces().First(x => !(x.IsGenericType)  x == typeof(IEnumerable));
    19.  
    20.             if (listType == null)
    21.                 throw new ArgumentException("Object does not implement IEnumerable interface", "enumerable");
    22.  
    23.             var method = listType.GetMethod("GetEnumerator");
    24.  
    25.             if (method == null)
    26.                 throw new InvalidOperationException("Failed to get 'GetEnumerator()' method info from IEnumerable type");
    27.  
    28.             IEnumerator enumerator = null;
    29.  
    30.             try
    31.             {
    32.                 //Create a delegate instance to get the enumerator
    33.                 var enumeratorDelegate = (GetEnumerator) Delegate.CreateDelegate(typeof (GetEnumerator), enumerable, method);
    34.                
    35.  
    36.                 //Create the enumerator by executing the delegate.  
    37.                 //This is much faster than using Invoke
    38.                 enumerator = enumeratorDelegate();
    39.  
    40.                 if (enumerator != null)
    41.                 {
    42.                     while (enumerator.MoveNext())
    43.                     {
    44.                         action((T)enumerator.Current);
    45.                     }
    46.                 }
    47.                 else
    48.                 {
    49.                     UnityEngine.Debug.Log("GetEnumerator() returned null.");
    50.                 }
    51.             }
    52.             finally
    53.             {
    54.                 var disposable = enumerator as IDisposable;
    55.  
    56.                 if (disposable != null)
    57.                     disposable.Dispose();
    58.             }
    59.         }
    60.     }
    61. }
    62.  
     
    Last edited: Oct 22, 2013
  11. Sisso

    Sisso

    Joined:
    Sep 29, 2009
    Posts:
    196
    Adding some knowledge to the thread.

    The same exception could happens if you build a generic array with null values in UnityScript and try to serialize using JsonFx.
     
  12. Roland1234

    Roland1234

    Joined:
    Nov 21, 2012
    Posts:
    190
    I tried running several timed tests in MS .NET between using the Invoke method and constructing a delegate but didn't discern any significant difference between the two - although everything one reads online asserts that using MethodInfo.Invoke is much slower. I don't know, I didn't really see that. Maybe there's been optimizations done to the framework since or my testing is simply flawed.

    Once I ported it over to Unity and tried running some tests in Mono I got the following error:
    pointing to the line where the delegate is actually executed to get the IEnumerator. Not sure what's going on there since the construction and casting of the delegate seems to be working, but it looks like the result is an invalid delegate.

    Finally, a couple of (mostly) insignificant nitpicks - the lines:
    Code (csharp):
    1.  
    2. var listType = enumerable.GetType().GetInterfaces().First(x => !(x.IsGenericType)  x == typeof(IEnumerable));
    3. if (listType == null)
    4. {
    5.     throw new ArgumentException("Object does not implement IEnumerable interface", "enumerable");
    6. }
    7. var method = listType.GetMethod("GetEnumerator");
    8.  
    could/should simply be
    Code (csharp):
    1.  
    2. var enumerableType = typeof(IEnumerable);
    3. if(!enumerable.GetType().GetInterfaces().Contains(enumerableType))
    4. {
    5.     throw new ArgumentException("Object does not implement IEnumerable interface", "enumerable");
    6. }
    7. var method = enumerableType.GetMethod("GetEnumerator");
    8.  
    Of course both will throw exceptions if the enumerable object does not actually implement IEnumerable, but you'll get a generic "sequence contains no matching elements" exception if it throws in the execution of .First. Also, it shouldn't be necessary to check !x.IsGenericType as typeof(IEnumerable).IsGenericType will always be false as opposed to typeof(IEnumerable<>).IsGenericType which will always be true.

    Or else it was intended as is due to the nature of the original problem and I don't know what I'm talking about.

    PS - Oh and I'd suggest caching the IEnumerable Type and GetEnumerator MethodInfo in a static class to limit the amount of reflection as much as possible.
     
    Last edited: Nov 3, 2013
  13. Dustin-Horne

    Dustin-Horne

    Joined:
    Apr 4, 2013
    Posts:
    4,568
    Roland -

    Interesting, thanks for the info. My guess is that it's actually the opposite. Mono probably lacks some of the optimization that the Microsoft implementation uses which makes the delegate version not perform any better.
     
  14. FredDeschenes

    FredDeschenes

    Joined:
    Mar 15, 2013
    Posts:
    21
    Update : we had the same issue again in other modules, we managed to get it working by doing a simple
    Code (csharp):
    1.  
    2. IList myList;
    3.  
    4. for(int i = 0; i < myList.Count; i++)
    5. {
    6.     var myItem = myList[i];
    7. }
    8.  
    I'll update if we encounter other issues with this!
     
  15. Dustin-Horne

    Dustin-Horne

    Joined:
    Apr 4, 2013
    Posts:
    4,568
    Yes this will work just fine as long as you're working with a list or an array (or a collection that supports indexing) since it doesn't require an enumerator. If you're accepting a generic argument though, such as IEnumerable<T>, or working with a Dictionary<TKey, TValue> you don't have the option of using an indexer which is why you'd need the ForEach implementation.
     
  16. JaredThirsk

    JaredThirsk

    Joined:
    Jan 17, 2010
    Posts:
    38
    Also, be careful with generic interface dispatch even with lists! I would expect the following to fail:

    Code (csharp):
    1.  
    2. IList<MyType> myList;
    3.  
    4. for(int i = 0; i < myList.Count; i++)
    5. {
    6.     var myItem = myList[i];
    7. }
    8.  
    (Possibly with different failure characteristics depending on whether MyType is a reference or value type, although I expect both to be unreliable.)
     
  17. FredDeschenes

    FredDeschenes

    Joined:
    Mar 15, 2013
    Posts:
    21
    Yeah this obviously only works with lists, although you can use regular for loops with IEnumerable<T> (untested on iOs though):

    Code (csharp):
    1.  
    2. IEnumerable<T> myEnumerable;
    3. for(int i = 0; i < myEnumerable.Count(); i++)
    4. {
    5.     var temp = myEnumerable.ElementAt(i);
    6. }
    7.  
    We've also had issues with using 'IList' without the generic parameter on iOs (crashes with the same error message when 'foreach'ing over the collection).

    I haven't experienced any issues with this except with List<T : ValueType> on iOs where the list sometimes becomes filled with 0s.
     
    Last edited: Nov 7, 2013
  18. Claytonious

    Claytonious

    Joined:
    Feb 16, 2009
    Posts:
    904
    Did you guys ever file a bug report with UT as requested? If so, what's the status?
     
  19. Mantas-Puida

    Mantas-Puida

    Joined:
    Nov 13, 2008
    Posts:
    1,864
    Fix for this bug is scheduled for next upcoming release of Unity
     
  20. FredDeschenes

    FredDeschenes

    Joined:
    Mar 15, 2013
    Posts:
    21
    Thanks Mantas! I'm guessing this means that the Mono runtime included with Unity is getting updated? If so, do you know which version it'll be and is it comparable to the current MonoTouch version (we have tried reproducing our AOT errors on MonoTouch/Xamarin and can't)?
     
  21. Mantas-Puida

    Mantas-Puida

    Joined:
    Nov 13, 2008
    Posts:
    1,864
    No. It is just fix for this problem.
     
  22. FredDeschenes

    FredDeschenes

    Joined:
    Mar 15, 2013
    Posts:
    21
    Then I'm kind of disappointed then :( The amount of issues we have with AOT compilation that are already fixed in newer Mono releases is pretty high...
     
  23. Dustin-Horne

    Dustin-Horne

    Joined:
    Apr 4, 2013
    Posts:
    4,568
    That's great news! I didn't expect it to be fixed because it's a mono / aot bug, not a Unity bug. So most likely this does mean we will see an updated runtime. :)
     
  24. Claytonious

    Claytonious

    Joined:
    Feb 16, 2009
    Posts:
    904
    Thanks very much for the update and for the upcoming fix, Mantas. Is there any way for those of us affected to get a preview release of the fix? Or to include it on the beta channel maybe?
     
  25. Claytonious

    Claytonious

    Joined:
    Feb 16, 2009
    Posts:
    904
    Also, with respect to FredDeschenes's question above, what is/are/were the barriers to full parity with Xamarin and MonoTouch in Unity's Mono? Is the relationship between the companies unhealthy in some way, or are there technical obstacles? The Xamarin stack with AOT on iOS is so incredibly mature and rich. It's always a shame that Unity isn't "there yet" on so much of Xamarin's progress.

    Is there anything that those of us who are customers of both companies can do? Would it be helpful for us to make feature requests of some kind to Xamarin that would make this easier?
     
  26. bfriedman

    bfriedman

    Joined:
    Aug 6, 2012
    Posts:
    18
    So, I guess the question then arrises: When you have something like this going on within the mono stack, is it something we theoretically can actually fix ourselves or are we really stuck waiting for a full Unity release? This "could" be a show-stopper for many projects. And really, going in and completely refactoring your application code-with a work-around isn't great advice unless its truly the only thing you can do.

    You guys have your mono source on git:

    https://github.com/Unity-Technologies/mono/compare/unity-staging-aot

    And I'm sure one of those commits is this fix and one of those branches is the right mono for the player. Though I don't want to dig too much into the repo ATM.

    The question is: is Unity built in such a way, that we can effectively rebuild the mono that it's running on, or the players are running on, from your sources? In order to get these kinds of critical bug-fixes into our production versions of unity.

    Is it something that's technically do-able if you have the right kind of support staff in-house? Or is Unity built in such a way that truly, we really have to wait for you to do any kind of release to get a mono bug fix into the pipe?

    If so, is there any documentation out there as to how to go about it as a starting point?

    Open source being open source, you'd get a lot of extra hands helping you out if it turns out your user base can do this. And it would make unity a more responsible and mature product.
     
    callen likes this.
  27. FredDeschenes

    FredDeschenes

    Joined:
    Mar 15, 2013
    Posts:
    21
    @bfriedman : I sadly really doubt that this is possible without re-building the complete Unity stack yourself (editor, players, compiler, etc). Being able to use any Mono version that we wish (understanding that this could create bugs in itself) would be a great feature though.
     
  28. bfriedman

    bfriedman

    Joined:
    Aug 6, 2012
    Posts:
    18
    It's not even really about using "any mono" you wish. It's about being able to rebuild and link (dynamically obviously) the exact one they shipped with. With just a bug fix or two in-line. If this were mostly statically linked c++ it would of course, be a nightmare. But since it's mono, nearly everything is actually dynamically linked, even if it appears to be statically linked. At a bare minimum, I'd expect if you just copy over a lot of the managed .dll files with ones built from the right sources, they'd probably link in without issue. I don't think they're signing assemblies and such. So if this fix resides in a managed .dll that we could recompile with a patch and replace, that would probably work fine. If it is inside the C or C++ part of mono and is statically linked into the unity executable, that's another matter. But in truth, they could probably do minimal work and get that dealt with by dynamically linking unity's binary with a lib-mono with the right symbols. This is something I've had to do a lot of to get python.net to work correctly with DCC applications like maya and nuke and such. I actually think it's probably do-able if the git repository appears to be what it is, and unity isn't doing something extra and special behind the scenes that we're not aware of when they build. But if unity provided a map, that would help a lot.
     
  29. dcsan

    dcsan

    Joined:
    Oct 20, 2013
    Posts:
    1
    this was posted a couple of months ago now, and we still haven't seen a patch release that fixes it.
    it's preventing us (and others i imagine) from releasing iOS games.

    is this going to be part of 4.6? or before.. ?
     
  30. Mantas-Puida

    Mantas-Puida

    Joined:
    Nov 13, 2008
    Posts:
    1,864
    It's going to be part of 4.5, which is reaching RC1 soon. But if you are in hurry my advice would be try refactoring code to not use calls via interfaces.
     
  31. Zenix

    Zenix

    Joined:
    Nov 9, 2009
    Posts:
    213
    Wow. Only 3 years to fix a system critical bug. That must be a new Unity record?
     
  32. Kujo87

    Kujo87

    Joined:
    Sep 16, 2013
    Posts:
    168
    I'm getting this same issue on iOS when I serialise an object using LitJSON. My code works fine until I come to save it into playerprefs, then it causes this error. I use for loops with this data elsewhere in the game and it works fine - its only when serialising it do I get an issue. Are their any suggested workarounds for this in the mean time? Why would this only be an issue on serialisation?
     
  33. Kujo87

    Kujo87

    Joined:
    Sep 16, 2013
    Posts:
    168
    Also, which is strange - I only get this issue when in release mode. It seems to work fine when I'm debugging...
     
  34. mayofunk

    mayofunk

    Joined:
    Feb 21, 2014
    Posts:
    1
    @FeatureCreep
    Thanks!!!
     
  35. keomanla

    keomanla

    Joined:
    Jan 30, 2012
    Posts:
    26
    For the people who seeking for the answer to "System.String doesn't implement interface System.Collections.IEnumerator" crash

    Just need to remove all Debug.log about the object you are going to Serialize.

    For example if you are going to use JsonFx to Serialize() a IDictionary or a Hashtable, avoid having Debug.log which receive IDictionary/Hashtable or its keys/values as parameter.

    Of course you might curios to know if whatever will Serialize is correct or not, my suggestion is to Debug.Log the result string from Serialize(). Before calling Serialize(), don't Debug.Log the object.

    There might be something wrong with Debug.Log in this specific case.

    Hope this helps.
     
  36. Mantas-Puida

    Mantas-Puida

    Joined:
    Nov 13, 2008
    Posts:
    1,864
  37. Zenix

    Zenix

    Joined:
    Nov 9, 2009
    Posts:
    213
    I couldn't find any mention of it in the release notes. Was it just fixed quietly behind the scenes?
     
  38. Mantas-Puida

    Mantas-Puida

    Joined:
    Nov 13, 2008
    Posts:
    1,864
    http://unity3d.com/unity/whats-new/unity-4.5 : "Fixed mono AOT issue when calls are made via interface.". Maybe it's bit cryptic, but it actually tells what was fixed.
     
  39. Zenix

    Zenix

    Joined:
    Nov 9, 2009
    Posts:
    213
  40. rekillgore

    rekillgore

    Joined:
    Sep 10, 2012
    Posts:
    1
    I am still seeing this error message in Unity 4.5.4 in Mac OSX builds. We are getting many seemingly random crashes on our Mac builds. The Windows and Linux builds are performing well and do not crash. Any chance this error is the same issue as perviously mentioned in the thread?

    System.Byte[] doesn't implement interface System.IEquatable<System.String>

    * Assertion: should not be reached at mini-trampolines.c:183



    Receiving unhandled NULL exception

    Obtained 7 stack frames.

    #0 0x007fff84e10d46 in __kill

    #1 0x00000101afa68b in g_log

    #2 0x000001019d80cb in mono_convert_imt_slot_to_vtable_slot

    #3 0x000001019d76b6 in mono_magic_trampoline

    #4 0x00000102de8171 in (Unknown)

    #5 0x00000110205379 in System.Collections.Generic.GenericEqualityComparer`1<object>:Equals (object,object) + 0x69 (0x110205310 0x11020537e) [0x10875fcc0 - Unity Root Domain]

    #6 0x00000102f62293 in SmartFoxEventListeners:OnExtensionResponse (Sfs2X.Core.BaseEvent) + 0x153 (0x102f62140 0x102f622ed) [0x10875fcc0 - Unity Root Domain]
     
  41. Mantas-Puida

    Mantas-Puida

    Joined:
    Nov 13, 2008
    Posts:
    1,864
    We have never seen anything like that on OSX standalone builds. And the problem discussed above was very AOT specific. Please submit your project as bugreport.
    Thanks!
     
  42. jgraham821

    jgraham821

    Joined:
    Aug 21, 2014
    Posts:
    1
    Do you have any more information on why Debug.Log is causing this issue? Also, I would be curious as to how you discovered this for my own understanding. Any more insight you could provide would very much be appreciated. Thanks.