System.AccessViolationException 的奇怪问题
我有一个 asp.net (3.5) Web 应用程序。 在一个页面中,我使用一个非托管 C 库(模拟器),它根据某些输入生成一组结果。
当我在 web.config(发布模式)中设置 debug="false"
时,该调用将导致 System.AccessViolationException
。如果我在调试器中,或者至少在 web.config 中设置 debug="true"
,则该异常将永远出现。
由于错误的性质,我将调用放在 try-catch
中来记录异常,然后异常就不会出现!
在调试模式和/或 try-catch 中,受保护的内存空间是否有一些神奇的工作?
I have an asp.net (3.5) web application.
In one page i use an unmanaged C library (a simulator) that produces a set of results based on some input.
When i've set the debug="false"
in web.config (Release mode) that call will result in a System.AccessViolationException
. If i am in the debugger, or at least set debug="true"
in web.config, that exception will never appear.
Because of the nature of the bug i placed the call inside a try-catch
to log the exception and then the exception does not appear!
Is there some magical work on protected memory space when in debug mode and/or in a try-catch?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
在这种情况下,
AccessViolationException
可能意味着您的非托管 C 代码出现了问题。它覆盖了堆或其他东西。请记住,许多代码从来都不是为了在 ASP.NET 等多线程环境中运行而编写的。它们甚至从未在这样的环境中进行过测试,或者仅使用不适用于 ASP.NET 的某种“桌面”形式的多线程进行了测试。
我曾经遇到过这样的问题。声称线程安全的第三方 DLL 非常不安全。通过将非托管调试器附加到 ASP.NET 工作进程,可以看到应用程序正在整个 C 运行时库堆上进行写入,并且堆对此进行了严厉的抱怨。没有人在听抱怨。
有必要将对这段代码的调用包装在一个
lock
块中——以确保一次只有一个线程可以调用它。即使在负载下,这也足以防止所有崩溃。这仍然可能不足以满足所有非托管代码的需要。假设所有调用都发生在同一线程上,或者来自同一“会话”的所有调用发生在同一线程上的一段代码将会令人失望,并且很可能会崩溃或更糟糕的情况。在这种情况下,您可能需要将该代码移至单独的 Windows 服务中,该服务只允许一个线程访问该库,永远。
AccessViolationException
in this context probably means your unmanaged C code is screwing up. It's overwriting the heap or something.Keep in mind that many pieces of code were never written to be run in a multi-threaded environment like that of ASP.NET. They were never even tested in such an environment, or were only tested using some "desktop" form of multi-threading that does not apply to ASP.NET.
I had a problem like this once. A third-party DLL which claimed to be thread-safe was very unsafe. By attaching an unmanaged debugger to the ASP.NET worker process, it was possible to see that the application was writing all over the C runtime library heap, and the heap was complaining bitterly about it. And nothing was listening to the complaints.
It was necessary to wrap calls to this code in a
lock
block - to ensure that only one thread could call it at a time. This was sufficient to prevent all of the crashes, even under load.This still might not suffice for all unmanaged code. A piece of code that assumes all calls will occur on the same thread, or that all calls from the same "session" occur on the same thread, will be disappointed, and may very well crash or do something worse. In that case, you might need to move that code into a separate Windows Service which only allows one single thread to access that library, ever.