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("",""); } } |