Access Violation Exception during access of field of Object
在我的 .Net Core 2.0、ASP.Net react 项目中使用 Linq 时,我遇到了一个非常奇怪的行为:
当访问在 Linq "Select" 选择器中实例化的对象的字段时,它会抛出 "Access Violation Exception"
重现步骤(希望如此):
- 视觉工作室 2017、15.7.4
- 创建新的 ASP.Net Core 2.0 项目
- 选择"反应"模板
-
改变 SampleDataController.cs 如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15[HttpGet("[action]")]
public string Objects()
{
var rng = new Random();
var ret = Enumerable.Range(1, 5).Select(index =>
new TableDef("User")
.AddField(new StringField("ID", Guid.NewGuid().ToString()))
.AddField(new StringField("Name","User" + index.ToString()))
);
return"[" +
ret.Select(x => x.ToJSONString()).Aggregate((current, next) => current +"," + next) +
"]";
} -
具有以下类:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77public class TableDef
{
public string ID { get; private set; } = Guid.NewGuid().ToString();
public string LockedBy { get; private set; } ="";
public string Name { get; private set; }
public FieldDef[] Fields { get; private set; }
public TableDef(string name)
{
Name = name;
Fields = new FieldDef[0];
}
public TableDef AddField(FieldDef field)
{
field.Parent = this;
var flds = this.Fields;
Array.Resize(ref flds, flds.Length + 1);
flds[flds.Length - 1] = field;
this.Fields = flds;
return this;
}
public string ToJSONString()
{
return @" {""TableDef"": {""
""DefID"":""" + ID + @""",
""DefName"":""" + Name + @""",
""DefLockedBy"":""" + LockedBy + @"""}," +
Fields
.Select(x => ('"' + x.Name + @""" :""" + x.Value + '"'))
.Aggregate((current, next) => current +"," + next) +
"}";
}
}
public abstract class FieldDef
{
public string ID { get; protected set; } = Guid.NewGuid().ToString();
public string Name { get; protected set; }
public abstract string Value { get; set; }
public abstract string DefaultValue { get; set; }
public Boolean ReadOnly { get; protected set; } = false;
public Boolean IsDirty { get; set; } = false;
public TableDef Parent {
get { return Parent; }
set {
this.Parent = value;
ID = Parent.Name.Replace("","") +"_" + Name.Replace("","");
}
}
}
public class StringField : FieldDef
{
public override string Value {
get { return (IsDirty) ? Value : DefaultValue; }
set { this.Value = value; }
}
public override string DefaultValue { get; set; }
public StringField(string name, string defaultValue)
{
Name = name;
DefaultValue = defaultValue;
}
public StringField(string name, string defaultValue, Boolean readOnly)
{
Name = name;
DefaultValue = defaultValue;
ReadOnly = readOnly;
}
}
运行代码并单击"获取数据"链接时,应用程序完全死掉(至少在我的情况下),在 Visual Studio 中甚至没有出现错误。调试刚刚结束,给我留下以下调试输出:
1 2 3 | The program '[20584] dotnet.exe: Program Trace' has exited with code 0 (0x0). The program '[20584] dotnet.exe' has exited with code -1073741819 (0xc0000005) 'Access violation'. The program '[20584] dotnet.exe: Managed (CoreCLR)' has exited with code -1 (0xffffffff). |
当注释
我很确定这是我自己错误解释的一些继承的东西。
非常感谢任何帮助。谢谢。
好的,我发现了问题。访问冲突是由于堆栈溢出而发生的,在我看来这是违反直觉的(这就是我在这里发布它的原因)
当属性将值设置为自身时,堆栈溢出异常如何发生
由于我有 getter 和 setter 的实现,我不能再将属性用作"字段"(与仅指定 { get; set; }
时的"默认实现"相反
在实现getter和setter时需要使用单独的变量:
1 2 3 4 5 6 7 8 | private TableDef _parent; public TableDef Parent { get { return _parent; } set { this._parent = value; ID = Parent.Name.Replace("","") +"_" + Name.Replace("",""); } } |
恕我直言,这是反直觉的,因为编译器可以"创建"这样的代码,但作为程序员你不能。
看来,您正在递归设置 Parent 属性,这将导致 2-3 秒后堆栈溢出。您可以使用私有字段来存储父对象并在属性中使用它,如下所示。
1 2 3 4 5 6 7 8 | private TableDef _parent; public TableDef Parent { get { return _parent; } set { this._parent = value; ID = this._parent.Name.Replace("","") +"_" + Name.Replace("",""); } } |