1

我们一直在使用 OR 工具来解决实时 .NET 应用程序中的线性优化问题。也就是说,随着时间的推移,定期使用不同的输入解决线性优化问题。

最近,我们在服务器上长时间运行我们的应用程序时遇到了一个以前从未见过的问题,其中看似随机尝试解决优化问题导致 AccessViolationExceptions。具体来说,

Framework Version: v4.0.30319 Description: The process was terminated due to an unhandled exception. Exception Info: System.AccessViolationException at Google.OrTools.LinearSolver.operations_research_linear_solverPINVOKE.Variable_SolutionValue(System.Runtime.InteropServices.HandleRef) ...

我试图更具体地找出管道中发生这种情况的位置,但鉴于那里的输出,我相信这是我们试图在解决优化后从求解器中检索单个变量解决方案值的部分。

我们在相当数量的变量上使用了各种各样的约束。

有没有人见过这个?

4

1 回答 1

2

参考github问题链接

经过一些测试,我们发现似乎正在发生的事情是垃圾收集器正在收集我们在 P/Invoke 期间使用的一些变量,根据this

不幸的是,这似乎是 SWIG 创建其 .NET 包装器及其 IDisposable 实现方式的副作用,使用 HandleRefs 而不是SafeHandle之类的东西,它根据文档“处理”这个:

平台调用操作自动增加由 SafeHandle 封装的句柄的引用计数,并在完成时减少它们。这确保了句柄不会被回收或意外关闭。

更多信息在这里

不想涉足创建我们自己的 SWIG 类型映射或编译新版本的 SWIG 的业务,.NET 提供了一种方法来保持对象在垃圾收集器方面的“活动”。也就是说,在优化过程结束GC.KeepAlive时调用我们将通过 P/Invoke 访问值的所有对象(在我们的例子中是 Solver 和我们的变量),可以防止垃圾收集器认为它们是可收集的,直到没有副作用的方法范围结束(根据他们的文档)。KeepAlive

初步测试表明这是可行的,但鉴于它之前已经间歇性发生,我们将继续关注这种情况的发生。

展望未来,我认为向 SWIG 提出使用SafeHandles 的请求可能是最好的想法(之前已经讨论,并且仍然是一个悬而未决的问题),或者将类型映射更改为SafeHandle直接使用 s 可能是最好的选择。我可能会尝试自己研究后一个选项,但是因为这个修复最终只在我们的代码库中添加了 3 行代码(加上大量注释),看起来像是一个完整的修复,所以它对我来说将是低优先级。也就是说,对于即将发布的版本,对此进行修复会很好。

于 2017-11-16T23:51:12.600 回答