Search code examples
c#solidworksmemory-access

Solidworks, tracking down a Memory Access Violation Error on Isldworks.CloseDoc


I have two different functions inside an addon I have been working on in C#. Recently (Apparently) Solidworks has been crashing when it gets to certain parts of these two functions (possibly more, but these are the only two I have found it occurring in so far.) Under debug, both functions give me a "Memory Access Violation Error". This error occurs, every time, on the line where I am closing the active document, and occurs approximately 95% of the time.

It is almost always on the same part. It seems to be independent of run time, or number of parts that have been opened and closed. If I dont close the files, I dont seem to get the error. But when running a large assembly, that presents its own issues. Adding in a 1s wait before closing seems to reduce the frequency of the error (As in, I can occasionally get through the entire assembly without the error)

A quick explanation of what the function I am primarily concerned about is doing; It works from the top level of an assembly down, propagating the custom properties from the main assembly, and sub-assemblies, into their children. So I am constantly opening and closing different assembly and part files.

The code below has been stripped down to pretty much the bare minimum that replicates the error. The error occurs on line 59. From what Ive seen online so far, it it seems like these are hard to track down. Any help is greatly appreciated.

    public void propagateProps(bool overwrite)  
    {  
        List<string> assemblies = new List<string>();  
        string topAssem;  
        string compName = "";  
        int i = 0;  
        int j = 0;  
        int errors = 0, warnings = 0;  
        int partType = 1;  
        swModel = iSwApp.ActiveDoc;  
        if (swModel == null)  
        {  
            MessageBox.Show("No assembly document open. Please open an assembly and try again.", "Avengers Assemble Error");  
            return;  
        }  
        if (swModel.GetType() != 2)  
        {  
            MessageBox.Show("No assembly document open. Please open an assembly and try again.", "Avengers Assemble Error.");  
            return;  
        }  
        topAssem = swModel.GetPathName();  
        assemblies.Add(swModel.GetPathName());  
        swAssy = iSwApp.ActiveDoc;  
        while (i < assemblies.Count)  
        {  
            List<string> beenDone = new List<string>();  
            iSwApp.OpenDoc(assemblies[i], 2);  
            swModel = iSwApp.ActivateDoc(assemblies[i]);                  
            swAssy = iSwApp.ActiveDoc;  
            foreach (Component2 swComp in swAssy.GetComponents(true))  
            {  
                partType = 1;  
                compName = swComp.GetPathName();  
                if (compName.IndexOf(").SLD") > 0 || compName.IndexOf("REF") > 0)  
                {  
                    continue;  
                }  
                if (Path.GetExtension(compName).ToUpper() == ".SLDASM")  
                {  
                    partType = 2;  
                    assemblies.Add(compName);  
                }  
                iSwApp.OpenDoc(compName, partType);  
                swModel = iSwApp.ActivateDoc(compName);  
                if (swModel == null)  
                {  
                    continue;  
                }  


                #region things that might not be in  


            #endregion  


                boolstatus = swModel.Save3(5, errors, warnings);  
                System.Threading.Thread.Sleep(500);  
                iSwApp.CloseDoc(swModel.GetPathName());  
            swPart = null;  
            swModel = null;  
            }  
            ++i;  
            System.Threading.Thread.Sleep(500);  
        }  


        return;  
    }  

Update: After seeing this question; What's causing the memory access violation? I tried messing with some global variables I use in my functions to no effect. I have however managed to wrap my essential code in a different logical structure for looping through parts which seems to be avoiding this issue. But I feel thats a band-aid at best and would like to be able to avoid this problem in the future.


Solution

  • You're writing code in C# - unless you're working with PInvokes, unsafe blocks or similar, it should be impossible for you to cause memory access exceptions. The only reasonable answer then is that SolidWorks has a bug that either causes it to crash given reasonable inputs, or causes it to crash because it is not validating unreasonable inputs.

    The real fix would be to contact SolidWorks to have them reproduce the bug and fix it; barring that, we could analyze your code to look for interactions that are common triggers of bugs and faults. For instance, they may not be validating all of their input correctly - you could be providing invalid values that they're silently accepting; it doesn't break until much later.

    If you were accidentally passing null and they weren't checking, that could cause memory access violations if they later try to take a pointer from that null. If you were using resources after they were closed, and they weren't validating for such a condition, they may use a stale pointer under the hood, also causing a memory access violation.

    In other situations, asynchronous operations may be causing the fault - if you start some async operation and then close the resource tied to that operation, when that operation later progresses in the background, it could cause faults.

    It's possible that the way you're using handles returned to you is causing memory access violations. I noticed that you don't use the return value from OpenDoc, and instead attempt to access documents by other means. What happens when the return value from OpenDoc gets garbage collected? Maybe SolidWorks isn't properly reference counting, and thus when the return value is GC'd, the handle under the hood is closed and nulled; yet other operations still expect it to be valid, and thus cause memory access violations.

    It's also possible that you're using deprecated API - if so, you may be exercising code in SolidWorks that has a higher chance of being buggy because its no longer being tested or maintained. I noticed that you're invoking the OpenDoc method, which their documentation lists as deprecated. Consider using the recommended methods instead, such as OpenDoc6.

    Outside of fixing the real problem with the API either being broken, or not validating against broken inputs well enough, your only option is to investigate these sources of common API problems.