【问题标题】:Why is my stack trace being truncated?为什么我的堆栈跟踪被截断?
【发布时间】:2014-05-10 15:02:50
【问题描述】:

我有一个部分信任的 AppDomain,我在其中运行一个完全信任的调试窗口。使用PermissionSetAttribute 获取权限我可以创建窗口并用它做很多事情,但有时在数据绑定期间会抛出SecurityException。

一个容易重现的案例抛出这个:Property accessor 'Namespace' on object 'System.RuntimeType' threw the following exception:'Request failed.'。深入研究异常,我可以看到它是在需要完全信任时抛出的。

没问题,调试窗口程序集完全信任,我只需要断言它。但是当我查看内部SecurityException 的堆栈跟踪时,我看到了这个:

   at System.Security.CodeAccessSecurityEngine.Check(Object demand, StackCrawlMark& stackMark, Boolean isPermSet)
   at System.Security.CodeAccessSecurityEngine.Check(PermissionSet permSet, StackCrawlMark& stackMark)
   at System.Security.PermissionSet.Demand()
   at System.SecurityUtils.DemandGrantSet(Assembly assembly)
   at System.SecurityUtils.DemandReflectionAccess(Type type)
   at System.SecurityUtils.MethodInfoInvoke(MethodInfo method, Object target, Object[] args)
   at System.ComponentModel.ReflectPropertyDescriptor.GetValue(Object component)

到此结束,ReflectPropertyDescriptor.GetValue

在 Visual Studio 的调用堆栈窗口中,我可以在堆栈的最顶端看到 ReflectPropertyDescriptor.GetValue那个堆栈一直追溯到调试窗口的创建和我在那里执行的安全断言,这正是我想要的。

为什么堆栈会像这样被一分为二?我怎样才能阻止它发生?

我正在使用 .Net 4.0 安全性(即 2 级)。

【问题讨论】:

    标签: c# wpf stack-trace code-access-security


    【解决方案1】:

    这并不奇怪。 Visual Studio 的调用堆栈向您展示了抛出 current 异常时的方法。 InnerException 显示了 inner exception 异常发生位置的调用堆栈。在内部异常被抛出后,它向上传播调用堆栈,从而展开它直到它到达ReflectPropertyDescriptor.GetValue。那时,它被捕获在一个 catch 块中,并设置为一个新异常的内部异常,然后抛出并一直冒泡。所以第二个异常的调用堆栈从它被抛出的点开始(即ReflectPropertyDescriptor.GetValue

    这里有一个简单的例子来重现这个。

    namespace Exceptions
    {
        class ExceptionTester
        {
            public void Run()
            {
                ThrowSecondException();
            }
    
            public void DoSomething()
            {
                DoMore();
            }
    
            public void DoMore()
            {
                ThrowFirstException();
            }
    
            public void ThrowFirstException()
            {
                throw new FooException();
            }
    
            public void ThrowSecondException()
            {
                try
                {
                    DoSomething();
                }
                catch (FooException e)
                {
                    throw new BarException("derp", e);
                }
            }
        }
    
        class FooException : Exception
        {
    
        }
        class BarException : Exception
        {
            public BarException(string msg, Exception inner) : base(msg, inner)
            {
            }
        }
        class Program
        {
            static void Main(string[] args)
            {
                var tester = new ExceptionTester();
                tester.Run();
            }
        }
    }
    

    BarException 类型的第二个异常被抛出时,您会注意到Visual Studio 在调用堆栈的顶部有ThrowSecondException,因为这是BarException 被抛出的地方。但是,当您深入了解BarException's InnerException 并查看FooException's 调用堆栈时,它会显示FooException 被抛出的位置(ThrowFirstException())。

    【讨论】:

    • 有道理,谢谢。我已经能够稍微破解您的示例,以证明 CAS 堆栈遍历不受拆分的影响,因此看来我一直在寻找错误的区域。
    猜你喜欢
    • 2012-01-29
    • 2010-12-15
    • 2015-01-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-16
    • 1970-01-01
    相关资源
    最近更新 更多