zoukankan      html  css  js  c++  java
  • 托管调试中的对象标识

    问题是:
    也许您在调试时浏览了全局、局部或参数,然后通过一些丑陋的对象引用(如哈希表)来查找对象引用。你希望能在那个物体上获得一些身份,这样你就可以很容易地再次找到它。以后重新查找它可能不实际,特别是如果程序状态自上次以来已更改,以致原始步骤不再生成相同的对象。如果一个数据结构被更改,一个变量被重新分配,或者一个函数返回并使其所有的局部变量无效,那么很容易发生这种情况。事实上,在这种情况下,回溯原始步骤甚至可能产生完全不同的对象。
    解决方案是提供独立于其发现方式的“对象标识”。然后,不管程序状态发生了什么变化,都可以在以后根据其标识检索对象

    本机代码中的对象标识

    在本机代码中,通过“this”指针,每个对象都有一个内部标识。由于本机代码中没有GC移动对象,所以对象的地址是常量,只要对象还活着,就可以用来引用对象。


    例如,如果我知道地址0x0012eeff有一个Foo类型的对象,我可以通过检查“((Foo*)0x0012eeff)”随时查看它。地址提供了一个非常方便的固有对象标识。

    托管代码中的问题

    由于托管代码有一个GC来移动对象,所以转换地址不一定是安全的。地址可以是0x0012eeff,然后GC可以将其移动到0x44556677。托管代码的任何对象标识解决方案都需要与垃圾回收器协作。

    托管代码中的对象标识示例
    class Program
    
    {
    
        static void Main()
    
        {
    
            string s = "A test";
    
            Foo();
    
        }
    
        static void Foo()
    
        {
    
            object x = null;
    
            System.Console.WriteLine("In Foo:" + x); // <-- set Breakpoint here
    
        }
    
    }

    在Visual Studio 中试用:
    1) 运行到断点。
    2) 在断点处,将当前堆栈帧切换到Main()。
    3) 打开“Local”窗口。你应该看看当地的“s”。它的价值是“a test”。
    4) 右键单击“局部变量”窗口中的“s”,然后单击上下文窗口上的“生成对象ID”。该值现在显示“A test”{1}。VS创建了一个伪变量“1”,并将其别名为“s”。
    5) 现在切换回Foo()。
    6) 在locals窗口中,您将看到值为null的“x”。
    7) 将“x”的值设置为“1”。
    8) x的值现在是“A test”{1}!
    9) 跨过writeline,看看它实际上使用了这个新的x值。

    ICorDebug的工作原理:

    interface ICorDebugHeapValue2 : IUnknown
    
    {
    
        /*
    
          * Creates a handle of the given type for this heap value.
    
          *
    
          */
    
        HRESULT CreateHandle([in] CorDebugHandleType type, [out] ICorDebugHandleValue ** ppHandle);
    
    };

    这将返回从ICorDebugReferenceValue派生的ICorDebugHandleValue。HandleValue跟踪正在检查的对象的GC句柄。(回想起来,我认为我们应该将此ICorDebugStrongReferenceValue而不是HandleValue。HandleValue表示它对应于System.Runtime.InteropServices.GCHandle结构,但它不是)。
    调试器可以保留伪变量(如“1”)到ICorDebugHandleValue对象的映射。
    “type”指定句柄是“strong”还是“weak”。“Strong”(又名“normal”)句柄使对象保持活动状态,而“弱”句柄则无法保持对象的活动状态。这样做的一个副作用是,调试器现在可以创建强句柄来更改对象的寿命,从而允许调试器更改程序行为。(因此,只在调试器下重新编写bug的问题更加严重)。由于GCs和寿命已经是不确定的,这种扰动类似于调试器改变时间和暴露竞争条件的情况。
    V1.1试图在ICorDebug级别解决这个问题(通过ICorDebugReferenceValue::DereferenceStrong),但这是一个失败的设计。我们不赞成取消引用strong,而倾向于使用ICorDebugHandleValue。

  • 相关阅读:
    java中字符串截取
    Linux主机添加Windows字体
    oracle命令
    Oracle索引
    快速搜索多个word、excel等文件中内容
    oracle数据库修改字符集
    Linux服务器安装svn
    Linux定时任务增删改查等说明
    Linux按行读取文件内容
    linux远程通过shell脚本执行另一台linux机器上的shell文件
  • 原文地址:https://www.cnblogs.com/yilang/p/13906124.html
Copyright © 2011-2022 走看看