Access Violation Exception during access of field of Object

独自空忆成欢 提交于 2020-01-15 06:03:10

问题


I'm encountering a realy strange behaviour when using Linq in my .Net Core 2.0, ASP.Net react project:

When accessing a field of an object which gets instantiated inside an Linq "Select" selector, it throws an "Access Violation Exception"

Steps to reproduce (hopefully):

  • Visual Studio 2017, 15.7.4
  • Create new ASP.Net Core 2.0 Project
  • Choose "React" template
  • alter the SampleDataController.cs as follows:

    [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) +
            "]";
    }
    
  • With the following Classes:

    public 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;
        }
    }
    

When running the code and clicking on the "fetch data" link, the application dies (at least in my case) completely without even an error in Visual studio. The debugging just ends, leaving me with the following debug output:

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).

When commenting the line field.Parent = this; in public TableDef AddField(FieldDef field) the code runs smoothly. What may be worth noting is, that the program dies, even though I put a Breakpoint on this line. As this takes 2 or 3 seconds, I managed to read some variables from the field in the "Auto" intermediate window in the debugger, and they look perfectly fine. As soon as i try to access the parent field, the application dies though.

I'm pretty sure it's some inheritance stuff falsly interpreted by myself.

Any help is much appreciated. Thanks.


回答1:


Its seems, you are setting Parent property recursively, which will result in stack overflow after 2-3 seconds. You can use a private field to store Parent object and use it in property as below.

private TableDef _parent;
public TableDef Parent {
        get { return _parent; }
        set {
            this._parent = value;
            ID = this._parent.Name.Replace(" ", "") + "_" + Name.Replace(" ", "");
        }
    }  



回答2:


Ok, I found the problem. The access violation happens because of an stack overflow, which is in my opinion counter intuitive (which is why I'm posting it here)

How Stack over flow exception occurs when property sets value to Itself

As i have an implementation of the getter and setter, I can't use the Property as "field" anymore (opposing to the "default implentation" when just specifying { get; set; }

One need to use separate variable when implementing getters and setters:

private TableDef _parent;
public TableDef Parent {
    get { return _parent; }
    set {
        this._parent = value;
        ID = Parent.Name.Replace(" ", "") + "_" + Name.Replace(" ", "");
    }
} 

Imho it's counter intuitive, because the compiler can "create" such a code, but as programmer you can't.



来源:https://stackoverflow.com/questions/51253700/access-violation-exception-during-access-of-field-of-object

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!