10

我在 C# 中使用的插件中有两个不同的功能。最近(显然)Solidworks 在到达这两个函数的某些部分时一直崩溃(可能更多,但这是迄今为止我发现的仅有的两个。)在调试下,这两个函数都给我一个“内存访问冲突”错误”。每次在我关闭活动文档的行上都会发生此错误,并且大约有 95% 的时间会发生此错误。

它几乎总是在同一部分。它似乎与运行时间或已打开和关闭的部件数量无关。如果我不关闭文件,我似乎没有收到错误消息。但是在运行大型程序集时,就会出现问题。在关闭前添加 1 秒等待似乎可以降低错误的频率(如,我偶尔可以通过整个程序集而不会出现错误)

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

下面的代码已被精简到几乎可以复制错误的最低限度。错误发生在第 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;  
    }  

更新:看到这个问题后;是什么导致内存访问冲突?我尝试弄乱我在函数中使用的一些全局变量,但没有效果。然而,我设法将我的基本代码包装在不同的逻辑结构中,以便循环访问似乎可以避免这个问题的部分。但我觉得那充其量只是一个创可贴,并且希望将来能够避免这个问题。

4

1 回答 1

5

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

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

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

在其他情况下,异步操作可能会导致故障 - 如果您启动一些异步操作然后关闭与该操作相关的资源,当该操作稍后在后台进行时,它可能会导致故障。

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

也有可能您正在使用已弃用的 API - 如果是这样,您可能正在使用 SolidWorks 中的代码,由于不再对其进行测试或维护,因此出现错误的可能性更高。我注意到您正在调用该OpenDoc方法,他们的文档将其列为已弃用。考虑改用推荐的方法,例如OpenDoc6.

除了解决 API 被破坏的真正问题,或者没有足够好地验证被破坏的输入之外,您唯一的选择是调查这些常见 API 问题的来源。

于 2016-07-11T15:46:47.590 回答