C# malloc:**JSON反序列化期间未分配释放的对象指针错误

C# malloc:**JSON反序列化期间未分配释放的对象指针错误,c#,json,xamarin.mac,C#,Json,Xamarin.mac,我正试图在VisualStudioforMac的一个Xamarin.Mac项目中使用C#将JSON字符串反序列化到一个列表中 我可以序列化,但没有任何问题: using (StreamWriter file = File.CreateText(filename)) { var serializer = new JsonSerializer() { Formatting

我正试图在VisualStudioforMac的一个Xamarin.Mac项目中使用C#将JSON字符串反序列化到一个列表中

我可以序列化,但没有任何问题:

using (StreamWriter file = File.CreateText(filename))
            {
                var serializer = new JsonSerializer()
                {
                    Formatting = Formatting.Indented,
                    TypeNameHandling = TypeNameHandling.Auto,
                    TypeNameAssemblyFormatHandling = TypeNameAssemblyFormatHandling.Simple,
                    ReferenceLoopHandling = ReferenceLoopHandling.Ignore
                };
                await Task.Run(() => serializer.Serialize(file, contactroot));
            }
但当我尝试使用以下方法反序列化时,会出现上述错误:

var contacts = JsonConvert.DeserializeObject<ContactRoot>(json);
。。。还有很多类似的属性:

public DateTime? updated_at { get; set; }

    [Export("updatedString"), Display(Name = "Updated Date"), Category("Misc"), Description("3"), DefaultValue(TypeOfValue.DateTime)]
    public string updatedString
    {
        get {
            if (this.updated_at.HasValue){
                return this.updated_at.Value.ToString();
            } else{
                return string.Empty;
            }
        }
        set
        {
            WillChangeValue("updatedString");
            try
            {
                if (!String.IsNullOrEmpty(value)) this.updated_at = Convert.ToDateTime(value);
            }
            catch (Exception)
            {
            }
            DidChangeValue("updatedString");
        }
    }
我在用约会时间?因为API源需要,而且由于Xamarin数据绑定似乎不处理int或DateTime的null,所以我使用string属性来进行转换。这在使用应用程序时可以正常工作,但不确定这是否是导致反序列化错误的原因。 我刚开始为Mac开发,所以我可能错过了一些东西

编辑

哇,谢谢你的快速回复!在看到任何评论之前,我尝试了一个更简单的类,但得到了相同的结果:

[Register("SimpleContact")]
public class SimpleContact : NSObject
{
    int _id = 0;
    string _first = String.Empty;
    string _last = String.Empty;

    [Export("id")]
    public int id {
        get { return _id; }
        set {
            WillChangeValue("id");
            _id = value;
            DidChangeValue("id");
        }
    }

    [Export("first")]
    public string first {
        get { return _first; }
        set {
            WillChangeValue("first");
            _first = value;
            DidChangeValue("first");
        }
    }

    [Export("last")]
    public string last
    {
        get { return _last; }
        set
        {
            WillChangeValue("last");
            _last = value;
            DidChangeValue("last");
        }
    }

    [Export("fullname")]
    public string fullname
    {
        get { return this.first + " " + this.last; }
    }

    public SimpleContact()
    {}

    public SimpleContact(int id, string first, string last)
    {
        this.id = id;
        this.first = first;
        this.last = last;
    }

    public override string ToString()
    {
        return this.fullname;
    }
}
接下来,我将尝试POCO方法并发布结果。非常感谢你

编辑 以下是例外情况的实质。我认为例外情况的其余部分没有任何用处:

Crashed Thread:        0  tid_307  Dispatch queue: com.apple.main-thread

Exception Type:        EXC_CRASH (SIGABRT)
Exception Codes:       0x0000000000000000, 0x0000000000000000
Exception Note:        EXC_CORPSE_NOTIFY

External Modification Warnings:
Debugger attached to process.

Application Specific Information:
abort() called
WealthBox Addon(6016,0x11d9ae5c0) malloc: *** error for object 0x7fff7f110880: pointer being freed was not allocated


Thread 0 Crashed:: tid_307  Dispatch queue: com.apple.main-thread
0   libsystem_kernel.dylib          0x00007fff7f08223e __pthread_kill + 10
1   libsystem_pthread.dylib         0x00007fff7f138c1c pthread_kill + 285
2   libsystem_c.dylib               0x00007fff7efeb268 __abort + 144
3   libsystem_c.dylib               0x00007fff7efeb1d8 abort + 142
4   libsystem_malloc.dylib          0x00007fff7f0fa6e2 malloc_vreport + 545
5   libsystem_malloc.dylib          0x00007fff7f0fa4a3 malloc_report + 152
6   libsystem_malloc.dylib          0x00007fff7f0f2aff malloc_set_zone_name + 47
7   ???                             0x00000001162ad420 0 + 4666872864
8   ???                             0x000000011616c6a3 0 + 4665558691
9   ???                             0x0000000116275739 0 + 4666644281
10  ???                             0x0000000116265443 0 + 4666577987
11  ???                             0x000000011625cbd3 0 + 4666543059
12  ???                             0x000000011618480b 0 + 4665657355
13  ???                             0x00000001162755bb 0 + 4666643899
14  ???                             0x0000000116265443 0 + 4666577987
15  ???                             0x000000011625cbd3 0 + 4666543059
16  ???                             0x000000011618480b 0 + 4665657355
17  ???                             0x000000011618885b 0 + 4665673819
18  ???                             0x0000000116185c7b 0 + 4665662587
19  ???                             0x000000011618486b 0 + 4665657451
20  ???                             0x000000011609f303 0 + 4664718083
21  ???                             0x000000011609cc03 0 + 4664708099
22  ???                             0x000000011609c84e 0 + 4664707150
23  ???                             0x0000000116095663 0 + 4664677987
24  ???                             0x0000000116087a33 0 + 4664621619
25  Browning-Financial.WealthBox-Addon  0x000000010edc5593 mono_jit_runtime_invoke + 1443 (mini-runtime.c:2806)
26  Browning-Financial.WealthBox-Addon  0x000000010eeaee4f mono_runtime_invoke_checked + 127 (object.c:2887)
27  Browning-Financial.WealthBox-Addon  0x000000010eeb36fc mono_runtime_invoke + 76 (object.c:2941)
28  Browning-Financial.WealthBox-Addon  0x000000010ecadaa2 xamarin_invoke_trampoline + 6018 (trampolines-invoke.m:456)
29  Browning-Financial.WealthBox-Addon  0x000000010ecaec7d xamarin_arch_trampoline + 189 (trampolines-x86_64.m:547)
30  Browning-Financial.WealthBox-Addon  0x000000010ecb00b1 xamarin_x86_64_common_trampoline + 110
31  com.apple.AppKit                0x00007fff4f3deb5a -[NSViewController _sendViewDidLoad] + 97
32  com.apple.AppKit                0x00007fff4f3dbeb5 _noteLoadCompletionForObject + 645
33  com.apple.AppKit                0x00007fff4f24d99f -[NSIBObjectData nibInstantiateWithOwner:options:topLevelObjects:] + 2086
34  com.apple.AppKit                0x00007fff4f3e3114 -[NSNib _instantiateNibWithExternalNameTable:options:] + 679
35  com.apple.AppKit                0x00007fff4f3e2d70 -[NSNib _instantiateWithOwner:options:topLevelObjects:] + 136
36  com.apple.AppKit                0x00007fff4f3e1fdc -[NSViewController loadView] + 343
37  com.apple.AppKit                0x00007fff4f3ddb60 -[NSViewController _loadViewIfRequired] + 75
38  com.apple.AppKit                0x00007fff4f3ddacb -[NSViewController view] + 30
39  com.apple.AppKit                0x00007fff4f4d01da -[NSWindow _contentViewControllerChanged] + 109
40  com.apple.Foundation            0x00007fff540c7450 -[NSObject(NSKeyValueCoding) setValue:forKey:] + 331
41  com.apple.AppKit                0x00007fff4f3da987 -[NSWindow setValue:forKey:] + 111
42  com.apple.AppKit                0x00007fff4f32ce0c -[NSIBUserDefinedRuntimeAttributesConnector establishConnection] + 637
43  com.apple.AppKit                0x00007fff4f24d739 -[NSIBObjectData nibInstantiateWithOwner:options:topLevelObjects:] + 1472
44  com.apple.AppKit                0x00007fff4f3e3114 -[NSNib _instantiateNibWithExternalNameTable:options:] + 679
45  com.apple.AppKit                0x00007fff4f3e2d70 -[NSNib _instantiateWithOwner:options:topLevelObjects:] + 136
46  com.apple.AppKit                0x00007fff4fada64c -[NSStoryboard instantiateControllerWithIdentifier:] + 236
47  com.apple.AppKit                0x00007fff4f23e855 NSApplicationMain + 702
48  ???                             0x00000001151c56b7 0 + 4649146039
49  ???                             0x00000001151c53ab 0 + 4649145259
50  Browning-Financial.WealthBox-Addon  0x000000010edc5593 mono_jit_runtime_invoke + 1443 (mini-runtime.c:2806)
51  Browning-Financial.WealthBox-Addon  0x000000010eeaee4f mono_runtime_invoke_checked + 127 (object.c:2887)
52  Browning-Financial.WealthBox-Addon  0x000000010eeb5c2e mono_runtime_exec_main_checked + 110 (object.c:4782)
53  Browning-Financial.WealthBox-Addon  0x000000010ed1087f mono_jit_exec + 287 (driver.g.c:1210)
54  Browning-Financial.WealthBox-Addon  0x000000010ed1384a mono_main + 11114 (driver.g.c:2418)
55  Browning-Financial.WealthBox-Addon  0x000000010ecb0a8e xamarin_main + 1182 (launcher.m:661)
56  Browning-Financial.WealthBox-Addon  0x000000010ecb1a04 main + 36 (launcher.m:679)
57  libdyld.dylib                   0x00007fff7ef42ed9 start + 1

Thread 1:
0   libsystem_pthread.dylib         0x00007fff7f1353f8 start_wqthread + 0
1   ???                             0x0000000054485244 0 + 1414025796

Thread 2:: SGen worker
0   libsystem_kernel.dylib          0x00007fff7f07f7de __psynch_cvwait + 10
1   libsystem_pthread.dylib         0x00007fff7f139593 _pthread_cond_wait + 724
2   Browning-Financial.WealthBox-Addon  0x000000010ef7416e thread_func + 558 (mono-os-mutex.h:173)
3   libsystem_pthread.dylib         0x00007fff7f136305 _pthread_body + 126
4   libsystem_pthread.dylib         0x00007fff7f13926f _pthread_start + 70
5   libsystem_pthread.dylib         0x00007fff7f135415 thread_start + 13

Thread 3:: Finalizer
0   libsystem_kernel.dylib          0x00007fff7f07c1b6 semaphore_wait_trap + 10
1   Browning-Financial.WealthBox-Addon  0x000000010ee4c7a5 finalizer_thread + 293 (mono-os-semaphore.h:90)
2   Browning-Financial.WealthBox-Addon  0x000000010ef01b50 start_wrapper + 704 (threads.c:1004)
3   libsystem_pthread.dylib         0x00007fff7f136305 _pthread_body + 126
4   libsystem_pthread.dylib         0x00007fff7f13926f _pthread_start + 70
5   libsystem_pthread.dylib         0x00007fff7f135415 thread_start + 13

Thread 4:: Debugger agent
0   libsystem_kernel.dylib          0x00007fff7f07f3e6 __recvfrom + 10
1   Browning-Financial.WealthBox-Addon  0x000000010ed0515e socket_transport_recv + 78 (debugger-agent.c:1153)
2   Browning-Financial.WealthBox-Addon  0x000000010ecf5a7c debugger_thread + 28588 (debugger-agent.c:1558)
3   Browning-Financial.WealthBox-Addon  0x000000010ef01b50 start_wrapper + 704 (threads.c:1004)
4   libsystem_pthread.dylib         0x00007fff7f136305 _pthread_body + 126
5   libsystem_pthread.dylib         0x00007fff7f13926f _pthread_start + 70
6   libsystem_pthread.dylib         0x00007fff7f135415 thread_start + 13

Thread 5:
0   libsystem_pthread.dylib         0x00007fff7f1353f8 start_wqthread + 0
1   ???                             0x0000000054485244 0 + 1414025796

Thread 0 crashed with X86 Thread State (64-bit):
  rax: 0x0000000000000000  rbx: 0x000000011d9ae5c0  rcx: 0x00007ffee0f81a18  rdx: 0x0000000000000000
  rdi: 0x0000000000000307  rsi: 0x0000000000000006  rbp: 0x00007ffee0f81a50  rsp: 0x00007ffee0f81a18
   r8: 0x0000000000000000   r9: 0x0000000000989680  r10: 0x0000000000000000  r11: 0x0000000000000206
  r12: 0x0000000000000307  r13: 0x000000011597b000  r14: 0x0000000000000006  r15: 0x000000000000002d
  rip: 0x00007fff7f08223e  rfl: 0x0000000000000206  cr2: 0x00007fffb1d2c188

Logical CPU:     0
Error Code:      0x02000148
Trap Number:     133

在序列化/反序列化POD数据(普通旧数据,即只包含字段的get/set属性,没有关联的业务逻辑)时,最好始终坚持使用普通DTO(数据传输对象)

从这个意义上讲,您的ContactRoot类型是POD,但是ContactType不是POD(由于NSObject的继承)。对于这个场景,我将为Contact引入一个单独的DTO类型,它将遵循POD标准。您可以为联系人列表创建一个替代属性,并使用JsonIgnore和JsonProperty属性模拟所需的行为

快速片段:

public class ContactDto
{
    /* List relevant properties here */
}

public class ContactRoot
{
    [JsonIgnore] // Do not serialize this
    public List<Contact> Contacts { get; set; }

    [JsonProperty(Propertyname = nameof(Contacts)]
    public List<ContactDto> SerializableContacts { 
        get => Contacts?.Select(x => /* data extraction */).ToList();
        set => Contacts = value?.Select(x => /* data extraction */)?.ToList();
    }
}
public class ContactDto
{
/*请在此处列出相关属性*/
}
公共类ContactRoot
{
[JsonIgnore]//不要序列化此
公共列表联系人{get;set;}
[JsonProperty(Propertyname=nameof(联系人)]
公共列表序列化联系人{
get=>Contacts?.Select(x=>/*数据提取*/).ToList();
set=>Contacts=value?.Select(x=>/*数据提取*/)?.ToList();
}
}

另外:对于CLR语言,POD似乎被称为

OK,多亏了Evengy Nazarov为我指明了正确的方向,我有了一个有效的解决方案

首先,这是我简化课堂上的一节课:

public class ContactDto
{
    private string _fullname = String.Empty;

    public int id { get; set; }

    public string first { get; set; }

    public string last { get; set; }

    [JsonIgnore]
    public string fullname {
        get { return this.first + " " + this.last; }
        set { _fullname = value; }
    }
}
请注意,没有NSObject继承或属性装饰(除了
[JsonIgnore]

已将ContactRoot更改为:

public class ContactRoot
{
    [JsonIgnore] // Do not serialize this
    public List<SimpleContact> SimpleContacts { get; set; }

    [JsonProperty(PropertyName = nameof(Contacts))]
    public List<ContactDto> SerializableContacts { get; set; }
}
然后,我的新序列化方法:

var contactroot = new ContactRoot
            {
                SimpleContacts = DataSource.SimpleContacts,
                SerializableContacts = new List<ContactDto>()
            };

            foreach (var simplecontact in contactroot.SimpleContacts)
            {
                contactroot.SerializableContacts.Add(ConvertToDto(simplecontact));
            }

            var desktop = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);
            var filename = Path.Combine(desktop, "WBAddon.json");
            if (File.Exists(filename))
            {
                File.Delete(filename);
            }

            using (StreamWriter file = File.CreateText(filename))
            {
                var serializer = new JsonSerializer()
                {
                    Formatting = Formatting.Indented,
                    TypeNameHandling = TypeNameHandling.Auto,
                    TypeNameAssemblyFormatHandling = TypeNameAssemblyFormatHandling.Simple,
                    ReferenceLoopHandling = ReferenceLoopHandling.Ignore
                };
                await Task.Run(() => serializer.Serialize(file, contactroot));
            }
var contactroot=新的contactroot
{
SimpleContacts=DataSource.SimpleContacts,
SerializableContacts=新列表()
};
foreach(contactroot.SimpleContacts中的var simplecontact)
{
contactroot.SerializableContacts.Add(convertto(simplecontact));
}
var desktop=Environment.GetFolderPath(Environment.SpecialFolder.desktop);
var filename=Path.Combine(桌面,“WBAddon.json”);
if(File.Exists(filename))
{
删除(文件名);
}
使用(StreamWriter file=file.CreateText(文件名))
{
var serializer=new JsonSerializer()
{
格式化=格式化。缩进,
TypeNameHandling=TypeNameHandling.Auto,
TypeNameAssemblyFormatHandling=TypeNameAssemblyFormatHandling.Simple,
ReferenceLoopHandling=ReferenceLoopHandling.Ignore
};
wait Task.Run(()=>serializer.Serialize(file,contactroot));
}
和反序列化:

var jsettings = new JsonSerializerSettings
            {
                Formatting = Formatting.Indented,
                TypeNameHandling = TypeNameHandling.Auto,
                TypeNameAssemblyFormatHandling = TypeNameAssemblyFormatHandling.Simple,
                ReferenceLoopHandling = ReferenceLoopHandling.Ignore
            };
            string json = string.Empty;
            using (StreamReader file = new StreamReader(filename))
            {
                json = file.ReadToEnd();

            }

            var contactroot = JsonConvert.DeserializeObject<ContactRoot>(json);
            DataSource.SimpleContacts = new List<SimpleContact>();
            foreach (var contactdto in contactroot.SerializableContacts)
            {
                DataSource.SimpleContacts.Add(ConvertToContact(contactdto));
            }
var jsettings=new JsonSerializerSettings
{
格式化=格式化。缩进,
TypeNameHandling=TypeNameHandling.Auto,
TypeNameAssemblyFormatHandling=TypeNameAssemblyFormatHandling.Simple,
ReferenceLoopHandling=ReferenceLoopHandling.Ignore
};
string json=string.Empty;
使用(StreamReader文件=新StreamReader(文件名))
{
json=file.ReadToEnd();
}
var contactroot=JsonConvert.DeserializeObject(json);
DataSource.SimpleContacts=新列表();
foreach(contactroot.SerializableContacts中的var contactdto)
{
Add(ConvertToContact(contactdto));
}

像我希望的那样工作!现在我只需要创建一个包含所有70+属性的完整联系人类的dto版本。可能有更好的方法,但这可以完成工作。

此外,我注意到,在setter中,您正在捕获并静默地接受异常。您确定这没有掩盖某种错误吗?请参阅。嘿,dbc,我选择了不o捕获模型中的异常,因为xcode控件在每次击键时调用change事件。因此,当用户尝试使用databound Outline视图更新日期字段时,每次击键都会出现异常,直到字符串具有足够的字符将值转换为DateTime。理想情况下,我宁愿使用在end edit l时调用的事件ike是一个很好的旧.net DataGrid。但到目前为止,我在xamarin.mac的短时间内还没有找到与之等效的。我在尝试反序列化更简单的SimpleContact类时也遇到了同样的问题,因此我认为完整类中的沉默异常不会影响反序列化。我将编辑该问题并发布完整异常。Thanks Evgeny!你启发了我的解决方案。我从未见过像你这样的get&set方法,看起来超级酷。我不知道如何使用它们,它们是如何工作的?
public ContactDto ConvertToDto(SimpleContact simpleContact)
    {
        var contactdto = new ContactDto();
        foreach (PropertyInfo prop in simpleContact.GetType().GetProperties().Where(t => t.DeclaringType == typeof(SimpleContact)))
        {
            var value = prop.GetValue(simpleContact);
            if (value != null)
            {
                var prop2 = contactdto.GetType().GetProperty(prop.Name);
                prop2.SetValue(contactdto, value);
            }
        }
        return contactdto;
    }
public SimpleContact ConvertToContact(ContactDto contactDto)
    {
        var simplecontact = new SimpleContact();
        foreach (PropertyInfo prop in contactDto.GetType().GetProperties())
        {
            var value = prop.GetValue(contactDto);
            if (value != null)
            {
                var prop2 = simplecontact.GetType().GetProperty(prop.Name);
                prop2.SetValue(simplecontact, value);
            }
        }
        return simplecontact;
    }
var contactroot = new ContactRoot
            {
                SimpleContacts = DataSource.SimpleContacts,
                SerializableContacts = new List<ContactDto>()
            };

            foreach (var simplecontact in contactroot.SimpleContacts)
            {
                contactroot.SerializableContacts.Add(ConvertToDto(simplecontact));
            }

            var desktop = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);
            var filename = Path.Combine(desktop, "WBAddon.json");
            if (File.Exists(filename))
            {
                File.Delete(filename);
            }

            using (StreamWriter file = File.CreateText(filename))
            {
                var serializer = new JsonSerializer()
                {
                    Formatting = Formatting.Indented,
                    TypeNameHandling = TypeNameHandling.Auto,
                    TypeNameAssemblyFormatHandling = TypeNameAssemblyFormatHandling.Simple,
                    ReferenceLoopHandling = ReferenceLoopHandling.Ignore
                };
                await Task.Run(() => serializer.Serialize(file, contactroot));
            }
var jsettings = new JsonSerializerSettings
            {
                Formatting = Formatting.Indented,
                TypeNameHandling = TypeNameHandling.Auto,
                TypeNameAssemblyFormatHandling = TypeNameAssemblyFormatHandling.Simple,
                ReferenceLoopHandling = ReferenceLoopHandling.Ignore
            };
            string json = string.Empty;
            using (StreamReader file = new StreamReader(filename))
            {
                json = file.ReadToEnd();

            }

            var contactroot = JsonConvert.DeserializeObject<ContactRoot>(json);
            DataSource.SimpleContacts = new List<SimpleContact>();
            foreach (var contactdto in contactroot.SerializableContacts)
            {
                DataSource.SimpleContacts.Add(ConvertToContact(contactdto));
            }