C# Xamarin iOS new StackTrace()杀死应用程序:断言条件'klass’;不期而遇

C# Xamarin iOS new StackTrace()杀死应用程序:断言条件'klass’;不期而遇,c#,ios,xamarin.ios,mono,uikit,C#,Ios,Xamarin.ios,Mono,Uikit,我们正在开发一款Xamarin iOS应用程序,突然间,该应用程序在某些地方的一些日志代码上开始崩溃。除了应用程序本身之外,我们还有一个名为WKGMobile.ios的xamarin ios库,其中包含一个名为GenericTableViewCell的类,该类派生自UITableViewCell。在内部,我们重写了UITableViewSource.GetCell(UITableView tableView,nsindepath indepath),在那里,我们最终调用了一个虚拟方法调用Cell

我们正在开发一款Xamarin iOS应用程序,突然间,该应用程序在某些地方的一些日志代码上开始崩溃。除了应用程序本身之外,我们还有一个名为
WKGMobile.ios
的xamarin ios库,其中包含一个名为
GenericTableViewCell
的类,该类派生自
UITableViewCell
。在内部,我们重写了
UITableViewSource.GetCell(UITableView tableView,nsindepath indepath)
,在那里,我们最终调用了一个虚拟方法调用
CellDidLoad
,我们在应用程序的派生类中使用它来初始化单元格的一些数据并进行一些日志记录。然而,日志记录本身似乎不是问题,因为我可以用以下对
new StackTrace()
的毫无意义的调用来替换复杂的日志记录逻辑:

public override void CellDidLoad(CheckableCellData?数据)
{
_=新堆栈跟踪();
}
调试时,结果是打印到应用程序输出的以下异常消息:

2021-05-27 13:59:06.830061+0200 ClubmappAppIOS[2840:116592] error: * Assertion at /Users/builder/jenkins/workspace/archive-mono/2020-02/ios/release/mono/mini/mini-exceptions.c:882, condition `klass’ not met
=================================================================
    Native Crash Reporting
=================================================================
Got a abrt while executing native code. This usually indicates
a fatal error in the mono runtime or one of the native libraries
used by your application.
=================================================================
=================================================================
    Native stacktrace:
=================================================================
    0x10c802275 - /Users/wkg/Library/Developer/CoreSimulator/Devices/CBA6C26F-5AF5-4A20-91B3-6F3DE56A77A3/data/Containers/Bundle/Application/63A2CC35-6283-494B-A483-A7DBC1BBFE32/ClubmappAppIOS.app/ClubmappAppIOS : mono_dump_native_crash_info
    0x10c7f6dbe - /Users/wkg/Library/Developer/CoreSimulator/Devices/CBA6C26F-5AF5-4A20-91B3-6F3DE56A77A3/data/Containers/Bundle/Application/63A2CC35-6283-494B-A483-A7DBC1BBFE32/ClubmappAppIOS.app/ClubmappAppIOS : mono_handle_native_crash
    0x10c80188f - /Users/wkg/Library/Developer/CoreSimulator/Devices/CBA6C26F-5AF5-4A20-91B3-6F3DE56A77A3/data/Containers/Bundle/Application/63A2CC35-6283-494B-A483-A7DBC1BBFE32/ClubmappAppIOS.app/ClubmappAppIOS : sigabrt_signal_handler
    0x7fff6115a5fd - /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Library/Developer/CoreSimulator/Profiles/Runtimes/iOS.simruntime/Contents/Resources/RuntimeRoot/usr/lib/system/libsystem_platform.dylib : _sigtramp
    0x0 - Unknown
    0x7fff200fab94 - /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Library/Developer/CoreSimulator/Profiles/Runtimes/iOS.simruntime/Contents/Resources/RuntimeRoot/usr/lib/system/libsystem_c.dylib : abort
    0x10ca14d20 - /Users/wkg/Library/Developer/CoreSimulator/Devices/CBA6C26F-5AF5-4A20-91B3-6F3DE56A77A3/data/Containers/Bundle/Application/63A2CC35-6283-494B-A483-A7DBC1BBFE32/ClubmappAppIOS.app/ClubmappAppIOS : _ZL12log_callbackPKcS0_S0_iPv
    0x10c9eda35 - /Users/wkg/Library/Developer/CoreSimulator/Devices/CBA6C26F-5AF5-4A20-91B3-6F3DE56A77A3/data/Containers/Bundle/Application/63A2CC35-6283-494B-A483-A7DBC1BBFE32/ClubmappAppIOS.app/ClubmappAppIOS : monoeg_g_logv_nofree
    0x10c9edbaf - /Users/wkg/Library/Developer/CoreSimulator/Devices/CBA6C26F-5AF5-4A20-91B3-6F3DE56A77A3/data/Containers/Bundle/Application/63A2CC35-6283-494B-A483-A7DBC1BBFE32/ClubmappAppIOS.app/ClubmappAppIOS : monoeg_assertion_message
    0x10c9edbda - /Users/wkg/Library/Developer/CoreSimulator/Devices/CBA6C26F-5AF5-4A20-91B3-6F3DE56A77A3/data/Containers/Bundle/Application/63A2CC35-6283-494B-A483-A7DBC1BBFE32/ClubmappAppIOS.app/ClubmappAppIOS : mono_assertion_message
    0x10c7f3c5b - /Users/wkg/Library/Developer/CoreSimulator/Devices/CBA6C26F-5AF5-4A20-91B3-6F3DE56A77A3/data/Containers/Bundle/Application/63A2CC35-6283-494B-A483-A7DBC1BBFE32/ClubmappAppIOS.app/ClubmappAppIOS : mono_get_generic_context_from_stack_frame
    0x10c7f4171 - /Users/wkg/Library/Developer/CoreSimulator/Devices/CBA6C26F-5AF5-4A20-91B3-6F3DE56A77A3/data/Containers/Bundle/Application/63A2CC35-6283-494B-A483-A7DBC1BBFE32/ClubmappAppIOS.app/ClubmappAppIOS : get_method_from_stack_frame
    0x10c7f4a80 - /Users/wkg/Library/Developer/CoreSimulator/Devices/CBA6C26F-5AF5-4A20-91B3-6F3DE56A77A3/data/Containers/Bundle/Application/63A2CC35-6283-494B-A483-A7DBC1BBFE32/ClubmappAppIOS.app/ClubmappAppIOS : ves_icall_get_frame_info
    0x11381ff2d - Unknown
    0x11381fdbb - Unknown
    0x11381fa83 - Unknown
=================================================================
    Basic Fault Address Reporting
=================================================================
Memory around native instruction pointer (0x7fff6113133a):0x7fff6113132a  ff ff c3 90 90 90 b8 48 01 00 02 49 89 ca 0f 05  .......H...I....
0x7fff6113133a  73 08 48 89 c7 e9 e5 a2 ff ff c3 90 90 90 b8 53  s.H............S
0x7fff6113134a  00 00 02 49 89 ca 0f 05 73 08 48 89 c7 e9 cd a2  ...I....s.H.....
0x7fff6113135a  ff ff c3 90 90 90 b8 83 01 00 02 49 89 ca 0f 05  ...........I....
=================================================================
    Managed Stacktrace:
=================================================================
      at <unknown> <0xffffffff>
      at System.Diagnostics.StackFrame:get_frame_info <0x000dc>
      at System.Diagnostics.StackFrame:.ctor <0x0014a>
      at System.Diagnostics.StackTrace:init_frames <0x00252>
      at System.Diagnostics.StackTrace:.ctor <0x00092>
      at ClubmappAppIOS.Common.Views.TableView.CheckableClubmappCell.CheckableClubmappCell:CellDidLoad <0x001c2>
      at WKGMobile.IOS.Components.Views.DataPresentation.IGenericCell`1:SetData <0x002c0>
      at WKGMobile.IOS.Components.Views.DataPresentation.GenericDataViewSource`1:GetCell <0x00360>
      at WKGMobile.IOS.Components.Views.DataPresentation.Tables.GenericTableViewSource`1:GetCell <0x0013a>
      at <Module>:runtime_invoke_object__this___object_object <0x0036f>
      at <unknown> <0xffffffff>
      at UIKit.UIApplication:UIApplicationMain <0x00254>
      at UIKit.UIApplication:Main <0x000b2>
      at UIKit.UIApplication:Main <0x00132>
      at ClubmappAppIOS.Application:Main <0x00302>
      at <Module>:runtime_invoke_void_object <0x00198>
=================================================================
编辑2(添加一些代码): 显然,不使用任何日志记录也不是一个选项,只要我们的
GenericTableViewCell
类的任何后代中出现异常,mono运行时也会崩溃,并出现本机异常,从而使任何托管异常处理都过时

我正在添加一些我们的内部库代码:

这是似乎参与(或负责)这些崩溃的
GenericTableViewCell

public partial class MusicTableViewCell : GenericTableViewCell<MusicListData>
{
    public override float CellHeight => 80f;

    public override string CellIdentifier => "MusicTableViewCell";

    public MusicTableViewCell()
    {
    }

    protected MusicTableViewCell(IntPtr handle) : base(handle)
    {
        // Note: this .ctor should not contain any initialization logic.
    }

    public override void CellDidLoad(MusicListData? data)
    {
         _ = new StackTrace();
    }
}
公共抽象类GenericTableViewCell:UITableViewCell,IGenericCell其中TData:class,IDataPoint
{
公共抽象浮点单元格高度{get;}
公共抽象字符串CellIdentifier{get;}
公共TData?数据点{get;私有集;}
TData?IGenericCell.DataPoint{get=>DataPoint;set=>DataPoint=value;}
公共UIViewController?ParentViewController{get;internal set;}
UIViewController?IGenericCell.ParentViewController
{
get=>ParentViewController;
set=>ParentViewController=value;
}
公共GenericTableViewCell()
{
}
公共GenericTableViewCell(IntPtr句柄):基(句柄)
{
}
公共虚拟数据加载(TData?数据)
{
SelectedBackgroundView???=新建UIView();
SelectedBackgroundView.BackgroundColor=UIColor.Clear;
}
}
IGenericCell
接口定义如下:

公共接口IGenericCell,其中TData:class,IDataPoint
{
内部保护的TData?数据点{get;set;}
公共字符串单元标识符{get;}
UIViewController?ParentViewController{get;内部集合;}
内部虚拟void SetData(TData?newData)
{
if(数据点可标识为一次性)
{
一次性的,一次性的;
}
数据点=新数据;
CellDidLoad(新数据);
}
无效单元负载(TData?数据);
}
最后是
IDataPoint
界面:

public interface IDataPoint
{
    int Id { get; }
}
这是导致这些本机崩溃的示例实现:

public partial class MusicTableViewCell : GenericTableViewCell<MusicListData>
{
    public override float CellHeight => 80f;

    public override string CellIdentifier => "MusicTableViewCell";

    public MusicTableViewCell()
    {
    }

    protected MusicTableViewCell(IntPtr handle) : base(handle)
    {
        // Note: this .ctor should not contain any initialization logic.
    }

    public override void CellDidLoad(MusicListData? data)
    {
         _ = new StackTrace();
    }
}
公共部分类MusicTableViewCell:GenericTableViewCell
{
公共覆盖浮动单元高度=>80f;
公共重写字符串CellIdentifier=>“MusicTableViewCell”;
公共MusicTableViewCell()
{
}
受保护的MusicTableViewCell(IntPtr句柄):基本(句柄)
{
//注意:此.ctor不应包含任何初始化逻辑。
}
公共覆盖无效CellDidLoad(MusicListData?数据)
{
_=新堆栈跟踪();
}
}
现在,所有本机mono异常都提示泛型或泛型在上述类中的使用存在一些问题,因为mono运行时在
mono\u get\u generic\u context\u from_stack\u frame()
(请参见第编辑1节)中的断言中终止它显然试图收集有关类的泛型上下文的堆栈帧信息,该类一直迭代到继承树的根(很可能是
System.Object
),但未成功,因此在该树中,它会引发一个断言,因为它找不到所谓的
MonoGenericContext
。或者这就是我的理论

我仍然想知道,搜索泛型类失败的原因是什么,为什么这似乎只是我们的
GenericTableViewCell
(及其后代)中的问题,而不是任何其他泛型类中的问题

我能想到的唯一区别是,
GenericTableViewCell
的后代由Xamarin框架使用
myUITableView.DequeueReusableCell(mycellidentier)

编辑3 在调试程序中单步执行代码后,我有了以下新发现:

到目前为止,一切似乎都很好:

只有当虚拟接口方法
IGenericCell.SetData(TData?newData)
被推到堆栈上时,调试器才会分离,mono运行时也会死亡

SetData()
被推到堆栈上:

现在,从这种行为判断,我假设泛型接口中的这个虚拟方法
SetData()
就是罪魁祸首,就像mono运行时试图为dubugger提供调用堆栈信息一样(就像它为
new StackTrace()
抛出新异常()
)它使用
mono\u get\u generic\u context\u from\u stack\u frame()
方法检索有关泛型上下文的信息
mono\u-get\u-generic\u-context\u from\u stack\u frame()
然后在内部使用while循环和
mono\u-class\u-get\u-generic\u-class(klass)
在所有类上迭代,而不是在接口上迭代推送到堆栈上的方法在接口(而不是类)中声明和实现。因此,运行时找不到它正在查找的上下文和itera