Solidworks,如何追踪解决Isldworks.CloseDoc中的内存访问冲突错误?

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

更新:在看到这个问题后,我尝试操作一些函数中使用的全局变量并没有起到作用。不过,我已经成功地将我的关键代码包装在不同的逻辑结构中以避免此问题。但是我觉得这只是一种权宜之计,未来仍需要避免这个问题。


这个问题没有任何人提供意见吗? - Nick
1
你正在使用C#编写代码 - 除非你在使用PInvokes、不安全的块或类似的东西,否则你应该不可能引起内存访问异常。那么唯一合理的答案是SolidWorks存在一个错误,要么是因为它无法处理合理的输入而导致崩溃,要么是因为它没有验证不合理的输入而导致崩溃。你是否在任何地方传递了null?你是否尝试在对象关闭后使用它们?你是否使用任何异步操作?你是否提供了任何钩子? - antiduh
@antiduh,什么是异步操作?提供钩子是什么意思?OpenDoc可能是问题所在!我正在使用它,而不是OpenDoc6,在出现问题的两种方法中。我需要测试一下! - Nick
异步操作 - 一种通常立即返回但启动某些后台任务的操作,该任务将在未来的某个时间完成。Dotnet有此类API示例 - FileStream.BeginWrite,或者在C#中具有显式语言支持的情况下 - FileStream.AsyncWrite。同步版本将是FileStream.Write()。请注意,异步操作可以采用IO操作(文件写入),计算(假设的PiCalculator.BeginCalc( digits = 30000 )),或某些简单的状态更改 - myForm.BeginInvoke( (Action) delegate() { button.Text = "Sending.."; } ) - antiduh
1
@antiduh 是的,这个错误完全让我的Solidworks会话崩溃了,我无法从中获取任何数据,即使在调试模式下运行也是如此。我开始相信这可能是Solidworks安装或类似因素在我特定系统上的问题。我一直在另一个系统上运行半自动化测试(基本上,我有一个0-40的FOR循环不断调用这种方法),而且使用旧代码时,它直到第22个循环才崩溃。老实说,这很可能更多是Solidworks出现问题,而不是我的程序。正在进行更多测试,但现在看起来就是这样。 - Nick
显示剩余8条评论
1个回答

5
您正在使用C#编写代码 - 除非您正在使用PInvokes、不安全块或类似的东西,否则您不可能导致内存访问异常。那么唯一合理的答案是SolidWorks存在错误,要么是由于合理的输入导致它崩溃,要么是由于它没有验证不合理的输入而导致崩溃。
真正的解决方法是联系SolidWorks以复现并修复错误;如果无法做到这一点,我们可以分析您的代码以查找触发错误和故障的常见交互。例如,他们可能没有正确地验证所有输入-您可能提供了无效的值,他们默默地接受了它们;直到后来才会出现错误。
如果您意外传递了null并且他们没有进行检查,则在稍后尝试从该值为null的指针中获取指针时可能会导致内存访问违规。如果您在关闭资源后仍在使用它们,并且他们没有验证此类情况,则它们可能在底层使用过时的指针,也会导致内存访问违规。
在其他情况下,异步操作可能会导致故障-如果您启动了某些异步操作,然后关闭了与该操作相关联的资源,则当该操作稍后在后台进展时,它可能会导致故障。
可能是您使用返回给您的句柄的方式导致内存访问违规。我注意到您没有使用OpenDoc的返回值,而是尝试通过其他方式访问文档。当OpenDoc的返回值被垃圾回收时会发生什么?也许SolidWorks没有正确地引用计数,因此当返回值被垃圾回收时,底层的句柄会被关闭和清空;但是其他操作仍然期望它有效,并因此导致内存访问违规。
还有可能您正在使用已弃用的API-如果是这样,您可能正在使用SolidWorks中的代码,该代码具有更高的错误几率,因为它不再进行测试或维护。我注意到您正在调用OpenDoc方法,其文档将其列为弃用。请考虑改用推荐的方法,例如OpenDoc6
除了修复API存在错误或未充分验证损坏输入的真正问题之外,您唯一的选择就是调查这些常见API问题的来源。

1
正如我之前所说,其他问题可能会导致这个问题,使用OpenDoc6调用似乎已经解决了我的问题。谢谢! - Nick

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接