• We have updated our Community Code of Conduct. Please read through the new rules for the forum that are an integral part of Paradox Interactive’s User Agreement.

operation40

Private
Mar 18, 2015
14
0
So, I'm getting this error in my mod..
Read from location 00000041 caused an access violation.

Location changes ofc..

This happens on either creating the label or setting the text:
myStatsTextField = myStatsWindowPanel.AddUIComponent<UILabel>();
or
myStatsTextField.text = TextFields;

Frustrating thing is it's not consistant.. sometimes it will run for 5-10 minutes, other times it crashes immediately.
I suspect some kind of thread contention going on -- ie: game is updating the UIComponent at the same time I'm trying to..

Is there a safer way to do these calls?

Code:
========== OUTPUTING STACK TRACE ==================

000000013FFF30F4 (Cities) ShaderLab::FastPropertyName::Init
000000013FFF50B5 (Cities) ShaderLab::FastPropertyName::Init
000000013FFF542B (Cities) ShaderLab::FastPropertyName::Init
000000013FFA645B (Cities) Unity::Material::SetTexture
000000014003B683 (Cities) MaterialPropertyBlock::GetHash
0000000015F1BC01 (Mono JIT Code) (wrapper managed-to-native) UnityEngine.Material:SetTexture (int,UnityEngine.Texture)
0000000015F1BB48 (Mono JIT Code) UnityEngine.Material:SetTexture (string,UnityEngine.Texture)
0000000015F1BACA (Mono JIT Code) UnityEngine.Material:set_mainTexture (UnityEngine.Texture)
0000000015F1B91F (Mono JIT Code) ColossalFramework.UI.UIDynamicFont:get_material ()
0000000015F1B802 (Mono JIT Code) ColossalFramework.UI.UIDynamicFont:get_isValid ()
0000000015F1B018 (Mono JIT Code) ColossalFramework.UI.UILabel:Invalidate ()
0000000015F16FD3 (Mono JIT Code) ColossalFramework.UI.UIComponent:InitializeComponent ()
0000000015F16DD7 (Mono JIT Code) ColossalFramework.UI.UIComponent:OnEnable ()
0000000015F343FD (Mono JIT Code) ColossalFramework.UI.UITextComponent:OnEnable ()
0000000004FA8BBB (Mono JIT Code) (wrapper runtime-invoke) object:runtime_invoke_void__this__ (object,intptr,intptr,intptr)
000007FEDC3E3DF7 (mono) mono_set_defaults
000007FEDC3382A1 (mono) mono_runtime_invoke
000000013FF65633 (Cities) ScriptingArguments::AddString
000000013FF65257 (Cities) ScriptingArguments::AddString
000000013FE8D670 (Cities) ReportScriptingObjectsTransfer::operator=
000000013FE9018B (Cities) GetMonoBehaviourInConstructor
000000013FE90567 (Cities) GetMonoBehaviourInConstructor
000000013FF18439 (Cities) DestroyObjectHighLevel
000000013FF186A0 (Cities) DestroyObjectHighLevel
000000013FDECDDC (Cities) CollisionMeshData::AwakeFromLoadThreaded
000000014004668A (Cities) Mesh::GetRuntimeMemorySize
0000000004FDC0FB (Mono JIT Code) (wrapper managed-to-native) UnityEngine.GameObject:Internal_AddComponentWithType (System.Type)
0000000004FDC045 (Mono JIT Code) UnityEngine.GameObject:AddComponent (System.Type)
0000000004FE1861 (Mono JIT Code) UnityEngine.GameObject:AddComponent<object> ()
0000000015F8CEB4 (Mono JIT Code) ColossalFramework.UI.UIComponent:AddUIComponent<object> ()
0000000062AFA0A0 (Mono JIT Code) CSLStatsPanel.StatusWindowInterface:updateText (System.Collections.Generic.List`1<string>)
0000000062A9E1F0 (Mono JIT Code) CSLStatsPanel.ThreadingCSLStatsMod:getstats2 ()
0000000062A9A83D (Mono JIT Code) CSLStatsPanel.ThreadingCSLStatsMod:OnAfterSimulationTick ()

Thanks!
 
When it crashes on create, the dump is like the above (on setTexture)

When it crashes on .text update, I get this:
Code:
000000013FD40F49 (Cities) ScriptMapper::VirtualRedirectTransfer
000000013FD35990 (Cities) Unity::Material::BuildProperties
000000013FD35A12 (Cities) Unity::Material::SetShader
000000013FDCB5E3 (Cities) MaterialPropertyBlock::GetHash
0000000015DEBEFB (Mono JIT Code) (wrapper managed-to-native) UnityEngine.Material:set_shader (UnityEngine.Shader)
0000000015DEBAF1 (Mono JIT Code) ColossalFramework.UI.UIDynamicFont:get_material ()
0000000015DEB992 (Mono JIT Code) ColossalFramework.UI.UIDynamicFont:get_isValid ()
0000000015DEB1A8 (Mono JIT Code) ColossalFramework.UI.UILabel:Invalidate ()
0000000015E1FE6D (Mono JIT Code) ColossalFramework.UI.UILabel:OnTextChanged ()
0000000015E0413A (Mono JIT Code) ColossalFramework.UI.UILabel:set_text (string)

full output_logs:
crash on creating UILabel: http://pastebin.com/phMvijsg
crash on .text update: http://pastebin.com/nRqMTuM8
 
I have some UILabel and I have no problem at all to put a text in it with ".text = value;"
I also have no problem creating it.

I had none crashing issue (CSL catchs it I guess) when I had my panel or my label as variable but I forgot to initialize it (or wrongly done it).

If it help, here is part of my code for it:

Code:
    public class modSlider : UISlider
    {
        public UILabel _valueDisplayer;

        public void setSlider(modPanel panel, string Title,int reference, int min, int max, zarineButton associatedButton)
        {
            _valueDisplayer = (UILabel)panel.AddUIComponent(typeof(UILabel));
            this.value = reference;
           // stuff unrelated
        }

        protected override void OnValueChanged()
        {
            this._valueDisplayer.text = this.value.ToString();
        }

I have a slider setting the value and updating the UILabel each time there is a change. And so far no problem at all.
 
In both your (new) crash logs you can find this at the end:

0000000076F159ED (kernel32) BaseThreadInitThunk
000000007704C541 (ntdll) RtlUserThreadStart

That's the problem with thread safety. Can you upload the whole method that crashes (the one that updates the text)?
 
Last edited:
this method takes a list of strings and makes a label for each one, but keeps the labels in a list so it doesn't recreate them next time

CSLStatsPanelLabel is just a regular UILabel.. I haven't defined any overrides for it

Code:
    public class CSLStatsWindowPanel : UIPanel
    {
        public List<CSLStatsPanelLabel> m_textfields = new List<CSLStatsPanelLabel>();

        public void updateText(List<string> TextFields)
        {
            statlog.log("update text initialized=" + initialized.ToString() + " running=" + running.ToString());
            if (!initialized) return;
            if (running) return;
            running = true;
            string s = ""; bool usesinglefield = true; // <-- work around uses a single label
            
            CSLStatsPanelLabel myStatsTextField;
            for (int i = 0;  i < TextFields.Count; i++)
            {
                if (i >= m_textfields.Count && (!usesinglefield || i == 0))
                {  // create a new UILabel
                    myStatsTextField = this.AddUIComponent<CSLStatsPanelLabel>();
                    myStatsTextField.name = "CSLStatsLabel_" + i.ToString();
                    myStatsTextField.autoSize = true;

                    m_textfields.Add(myStatsTextField);
                }
                else 
                { // use an existing UILabel
                    if (usesinglefield)
                    {
                        s += TextFields[i] + "\n";
                        myStatsTextField = m_textfields[0];
                    }
                    else myStatsTextField = m_textfields[i];
                }

                if (!usesinglefield)
                {
                    statlog.log("setting name: " + myStatsTextField.name + " text:  " + TextFields[i]);
                    myStatsTextField.text = TextFields[i];  // <-- crashy
                }
            }

            if (usesinglefield) m_textfields[0].text = s; // <-- works great

            running = false;
        }
}

I'd prefer individual labels so I can get creative with resizing and auto arranging, but it's not looking so bad with just 1 label:
http://steamcommunity.com/sharedfiles/filedetails/?id=410645446
 
I think at some point you might try to set myStatsTextField to an uninitialized object with "else myStatsTextField = m_textfields;" thus when reaching "myStatsTextField.text = TextFields;" it goes *BOOM"

Your "bool usesinglefield = true;" avoiding you to enter this part might be a good sign that it might be the problem.
 
He would see the NullReferenceException in the console output if that would be the case, no?
EDIT: Probably a IndexOutOfRangeException though.
 
Last edited:
So you did try commenting the logging out and can confirm it still crashes? Because it's not really clear if you did.

You could try putting everything in try-catch and have a catch like this:
Code:
catch (Exception ex)
{
    statlog.log(ex);
    statlog.log(ex.ToString());
}
That could at least catch what you doing wrong. It's weird that you are not getting any errors caught by the game, as it's usually what happens.
 
Last edited:
to end all doubt I created a new mod which only tries to create labels on a panel

http://pastebin.com/EDyk9jyJ

it tries to create 30 labels in a UIPanel..

int mymaxlabelcount = 30;
You can delay crashing if you start that at 1 and increment by 1 on each call (instead of spamming them all at once), but it will still crash..

*edit* -- I don't get near 30 before crashing - I can get 3-6 on screen most of the time, then.. crash!

afaik -- memory access violations are a hard stop, and cannot be "caught".. but in my actual mod I have the method call wrapped in a try/catch anyway...
 
Last edited:
Look I don't know jack about working with the Unity.UI yet... but that pastebin looked a little umm off for what you were trying to test\do once I tried it out.
Mainly cause that test rig is rebuilding nearly everything on like *every single tick.

Here is a working sample adapted from your original testrig paste bin. This one works, or at least it seems too just fine, tested up to 20 ran for 30min without issue.
The key difference is the UIPanel and List of UILabels is built only once at thread creation via OnCreated() and stored in static mylabels, then just the labels are updated every ~3 seconds instead of rebuilding them every tick. Left some comments in the code. Again I'm no ninja but I hope it helps ya.

http://pastebin.com/UqTEZ5Tr
 
got your UI code in my mod now and it's working great !!

http://steamcommunity.com/sharedfiles/filedetails/?id=411503256

thanks again for all your help.. my onaftersimulationtick that checked tickcount % 100 seems to be responsible for all the crashing, cause I"m using the same updateText method that I pasted above and it's adding labels and updating them just fine now. your OnUpdate with framecount check seems way more stable
 
Your quite welcome, your issue actually gave me a chance to play around with gui stuff for the first time. Glad to here it's working for you, while that %100 thing definitely seemed like a problem to me what also definitely helped was moving the creation of the labels (vs. the updating) out from under the calls that executed on the frame updates though I kind of assumed that was just a 'bug' of the down and dirty sample\test code, and technically maybe it might have worked but if it did probably would have caused unnecessary perf issues. I see in you real code your already doing it right (only creating once or when necessary) or so it looked. :)
 
Last edited: