Solidworks,在 Isldworks.CloseDoc 上追踪内存访问冲突错误

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

我一直在使用 C# 开发的插件中有两个不同的函数。最近(显然)Solidworks 在执行这两个函数的某些部分时崩溃了(可能更多,但这是迄今为止我发现它发生的仅有的两个。)在调试下,这两个函数都给我一个 "Memory Access Violation Error".这个错误每次都会发生在我关闭活动文档的那一行,大约 95% 的时间都会发生。

它几乎总是在同一部分。 它似乎与 运行 时间或已打开和关闭的部件数无关。 如果我不关闭文件,我似乎不会收到错误消息。但是当 运行 是一个大型集会时,就会出现它自己的问题。 在关闭前添加 1s 等待似乎可以减少错误的频率(例如,我偶尔可以在没有错误的情况下完成整个程序集)

快速解释一下我主要关心的功能是做什么的;它从装配体的顶层向下工作,将自定义属性从主装配体和子装配体传播到它们的子装配体中。所以我不断地打开和关闭不同的装配体和零件文件。

下面的代码已被精简到几乎可以复制错误的最低限度。错误发生在第 59 行。从我目前在网上看到的情况来看,这些似乎很难追踪。非常感谢任何帮助。

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

更新:看到这个问题后; What's causing the memory access violation? 我试图弄乱我在函数中使用的一些全局变量,但没有效果。然而,我设法将我的基本代码包装在一个不同的逻辑结构中,以循环遍历似乎避免了这个问题的部分。但我觉得那充其量只是一个创可贴,希望以后能够避免这个问题。

您正在用 C# 编写代码 - 除非您正在使用 PInvoke、不安全块或类似的东西,否则您应该不可能导致内存访问异常。那么唯一合理的答案是 SolidWorks 有一个错误,要么导致它在给定合理输入的情况下崩溃,要么导致它崩溃,因为它没有验证不合理的输入。

真正的解决方法是联系 SolidWorks 让他们重现并修复该错误;否则,我们可以分析您的代码以寻找作为错误和故障的常见触发器的交互。例如,他们可能没有正确验证他们所有的输入——你可能提供了他们默默接受的无效值;它直到很久以后才坏。

如果您不小心传递了 null 而他们没有检查,如果他们稍后尝试从该 null 获取指针,则可能会导致内存访问冲突。如果您在资源关闭后使用它们,并且它们没有验证这种情况,它们可能会在幕后使用陈旧的指针,也会导致内存访问冲突。

在其他情况下,异步操作可能会导致错误 - 如果您启动某个异步操作然后关闭与该操作关联的资源,当该操作稍后在后台进行时,可能会导致错误。

您使用 returned 句柄的方式可能会导致内存访问冲突。我注意到您没有使用 OpenDoc 中的 return 值,而是尝试通过其他方式访问文档。当来自 OpenDoc 的 return 值被垃圾回收时会发生什么?也许 SolidWorks 没有正确地引用计数,因此当 return 值被 GC 时,引擎盖下的句柄被关闭并为空;然而其他操作仍然期望它是有效的,因此会导致内存访问冲突。

也有可能您使用的是已弃用的 API - 如果是这样,您可能在 SolidWorks 中使用代码,因为它不再被测试或维护,所以更有可能出现错误。我注意到您正在调用 OpenDoc method, which their documentation lists as deprecated. Consider using the recommended methods instead, such as OpenDoc6.

除了解决 API 被损坏或未充分验证损坏输入的真正问题之外,您唯一的选择是调查这些常见 API 问题的根源。