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 问题的根源。
我一直在使用 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 问题的根源。