首页 > 解决方案 > SIGABRT 抛出的 xamarin 在模型 c# 中形成自定义 getter/setter

问题描述

**

注意; 21-12-2018 - 更改了问题的名称以符合此问题的新实例。有关这方面的信息在底部。

**

我已经为这个错误苦苦挣扎了 3 周,尝试了我能想到的一切,甚至重新安装了 Visual Studio 2017。

首先是一些背景故事;

我正在开发一个可以订购三明治并且大部分重要功能都已完成的应用程序。在过去的 4 个月里,整个订购过程一直在运作。几周前有一个灾难周,保险丝盒烧坏导致停电。这不知何故破坏了防火墙,整个公司网络都瘫痪了。在安装 android studio 期间(与 visual studio/xamarin 一起)。几天后,Visual Studio 2017 的更新出错了,我完全重新安装并删除了 android Studio。然后错误开始出现。

大多数应用程序仍然可以正常工作,但是您可以登录、检查购物篮、浏览类别等;当在 REST 实现中调用特定函数时,应用程序关闭并且调试器显示致命信号 6 SIGABRT -6 错误。

12-07 12:57:29.409 F/ (20795): * 在 /Users/builder/jenkins/workspace/xamarin-android-d15-9/xamarin-android/external/mono/mono/mini/unwind.c 的断言: 640,条件 `cfa_reg != -1' 不满足

12-07 12:57:29.409 F/libc (20795): 致命信号 6 (SIGABRT), tid 20828 (Thread Pool Wor) 中的代码 -6, pid 20795 (e.Appnamehere)

下面的代码:

public async Task<ObservableCollection<T>> GetAllWithId<T>(Guid id)
{
    var t = typeof(T);
    var uri = GetURI<T>();
    ObservableCollection<T> oc = new ObservableCollection<T>();
    try
    {
        var tmpUri = "";
        // IF statements to determine URI, if no ifs succeed let run and catch exception.. ps. can be changed for typeswitch
        if (typeof(T) == typeof(Product)) { tmpUri = uri + "/incategory/" + id; }/*use category id inside*/
        if (typeof(T) == typeof(Order)) { tmpUri = uri + "/fromuser/" + id; }/*use user id*/
        var client = GetNewClient();
        using (client)
        {
            HttpResponseMessage result = await client.GetAsync(tmpUri);
            if (result.IsSuccessStatusCode)
            {
                var content = await result.Content.ReadAsStringAsync();
                Debug.WriteLine(content);             
                oc = JsonConvert.DeserializeObject<ObservableCollection<T>>(content);// <<<<<< SIGABRT THROWN HERE
                //* Assertion at /Users/builder/jenkins/workspace/xamarin-android-d15-9/xamarin-android/external/mono/mono/mini/unwind.c:640, condition `cfa_reg != -1' not met
            }
        }
    }
    catch (Exception ex)
    {
        Debug.WriteLine(@"ERROR {0}", ex.Message);
    }

    return oc;
}

有一种实现使用所有控制器使用的泛型。方法getURIgetNewClient分别构建对应类型的 URI 并返回客户端实例。

自开发开始以来,xamarin 核心和其他包还没有更新,因为这通常会破坏东西。所有软件包的当前版本与开发开始时(即没有错误时)相同。(底部的软件包和版本列表)。

该错误在最后 2 个版本的 newtonsoft.json 包上执行(错误从 v11.0.2 开始,然后我更新到 v12.0.1,错误仍然存​​在)。API 数据是从其中检索并按预期工作,并以正确的格式返回数据。调试器没有显示堆栈跟踪,但确实说错误通常是由本机单声道代码或依赖项使用的本机代码引起的。

如果有人需要更多信息,我很乐意提供,因为我无法在谷歌上找到任何关于如何解决这个问题的信息。

该错误也发生在所有模拟器上(从 512mb 到 2gb 内存,堆大小和渲染器不同。我无法使用物理设备进行测试,因为网络仍处于锁定状态,并且设备无法连接)

版本信息

更新; 它是固定的(我认为)。20-12-2018

我在 API 端显式构建对象并将它们作为相应类型的对象(即产品、订单等)而不是 var 发送。

在反序列化、重新序列化并再次重复之后,我最终得到了一个有效但效率极低的解决方案。

之后,我在模型的属性上剪切了几个自定义的 getter 和 setter。(这绝不是此问题的指定原因,但它有助于解决它。)

它仍然有效,然后我尝试使用问题中显示的原始代码行,它有效。

请注意,我确实重新安装了 Visual Studio 两次..(一次从 15.9.2 更新到 15.9.3 时,昨天将其卸载并安装了新更新 15.9.4)。

这是在旧分支上完成的,该分支仍然具有所有依赖项的原始版本。

总而言之,这个错误应该不是反序列化对象不匹配的错误导致的。这样的错误应该作为反序列化错误或类似的东西抛出,而不是抛出原生单声道展开错误。

(导致此错误的代码行被两个嵌套的 try-catch 块包围。)

更新..它又发生了21-12-2018

所以昨天错误消失了。我希望它是好的,但现在它再次发生。我将其缩小到产品型号。(由于最初的错误发生在加载产品和加载历史订单时,它们只共享相同的 API 方法,所以它必须存在,而且也是如此)。

抛出了同样的错误,除了现在历史订单仍然有效,除了产品没有。当我向我的模型添加自定义 getter 和 setter 时发生了这种情况。下面的代码;

public Object ProductImage {
             get { return ProductImage; }
             set {

                try
                {
                    if (value.ToString().Contains("/api/DynamicImages/getimageonly/"))
                    {
                        string imreBase64Data = Convert.ToBase64String(Constants.ObjectToByteArray(value));
                        ProductImage = string.Format("data:image/png;base64,{0}", imreBase64Data);
                    }
                    else
                    {
                        ProductImage = value;
                    }


                }
                catch (Exception ex) { ProductImage = value; }


            }
           //   get;set;//<-- when i use this instead no signal abort is thrown but the images wont load when they are retrieved as either a file or data from my own API. (images retrieved as link to external site still work, falling back to place holders still works too.)
        }

当我恢复到简单的 get;set; 有用。有接盘侠吗?笔记; 我更新了问题的名称以更具体地针对这个新问题。

标签: c#androidjsonxamarinmono

解决方案


根本原因是不间断的递归调用。
如:
ProductImage = value -> 它将再次触发 call setter。
结果,setter 被一次又一次地调用。

在 java 中,它会针对这种情况报告 stackoverflow 错误。
但是,在单声道中,它显示了这样的错误消息,调试不清楚。

解决方案是:

private Object _productImage;
public Object ProductImage {
    get { return _productImage; }
    set {
    ... 
    _productImage = {some value};
    }
}

推荐阅读