当一种方法调用另一种方法时,会发生什么?

San*_*box 4 language-agnostic computer-science

这类似于运行程序时会发生什么?,但不是一个骗局.

假设我有一个简单的控制台程序,有两个方法A和B.

    public static void RunSnippet()
    {
        TestClass t = new TestClass();
        t.A(1, 2);

        t.B(3, 4);
    }

    public class TestClass
    {
        public void A(int param1, int param2)
        {
            //do something
            C();
        }

        private void C()
        {
            //do
        }

        public bool B(int param1, int param2)
        {
            //do something
            bool result = true;

            return result;
        }
    }
Run Code Online (Sandbox Code Playgroud)

有人可以详细解释(但请用简单的英文简单说明),当RunSnippet调用方法A和方法B(并在内部调用其他方法)时会发生什么.我想了解引擎盖下真正发生的事情......意思是params如何通过,它们存储在哪里,本地变量发生了什么,返回值如何通过,如果另一个线程在A调用C时开始运行会发生什么,如果抛出异常将会发生什么.

Eri*_* J. 10

我不太清楚你正在寻找什么样的细节,但这是我在解释发生的事情时的刺激:

  1. 为您的可执行文件创建一个新进程.该进程有一个包含每个线程堆栈的堆栈段,一个静态变量的数据段以及一个称为堆的内存块,用于动态分配的内存,以及一个包含编译代码的代码段.
  2. 您的代码被加载到代码段中,指令指针被设置为main()方法中的第一条指令,代码开始执行.
  3. 对象t从堆中分配.t的地址存储在堆栈中(每个线程都有自己的堆栈).
  4. 通过将返回地址放在堆栈上的main()并将指令指针更改为tA()代码的开头来调用tA().返回地址与值1和2一起放在堆栈中.
  5. tA()通过将返回地址放在堆栈上的tA()并将指令指针更改为tC()代码的起始地址来调用tC().
  6. tC()通过将返回地址弹出到堆栈的tA()并将指令指针设置为该值来返回.
  7. tA()以与tC()类似的方式返回.
  8. 对tB()的调用与对tA()的调用非常相似,只是它返回一个值.返回该值的确切机制取决于语言和平台.通常,该值将在CPU寄存器中返回.

注意:由于您的方法非常小,现代编译器通常会"内联"它们而不是进行经典调用.内联意味着从方法中获取代码并将它们直接注入到main()方法中,而不是通过进行函数调用的(轻微)开销.

鉴于您的示例,我没有看到线程如何直接进入图片.如果您第二次启动可执行文件,它将在新进程中运行.这意味着它将获得它自己的代码段,数据段和堆栈段完全将它与第一个进程隔离开来.

如果你的代码是在一个在几个线程上调用main()的大型程序中运行的,那么它几乎就像前面描述的那样运行.代码是线程安全的,因为它不访问任何可能的共享资源,例如静态变量.线程1无法"看到"线程2,因为所有关键数据(值和指向对象的指针)都存储在线程的本地堆栈中.